IB/ipath: Shadow the gpio_mask register
Once upon a time, GPIO interrupts were rare. But then a chip bug in the waldo series forced the use of a GPIO interrupt to signal packet reception. This greatly increased the frequency of GPIO interrupts which have the gpio_mask bits set on the waldo chips. Other bits in the gpio_status register are used for I2C clock and data lines, these bits are usually on. An "unlikely" annotation leftover from the old days was improperly applied to these bits, and an unnecessary chip mmio read was being accessed in the interrupt fast path on waldo. Remove the stagnant unlikely annotation in the interrupt handler and keep a shadow copy of the gpio_mask register to avoid the slow mmio read when testing for interruptable GPIO bits. Signed-off-by: Arthur Jones <arthur.jones@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
Родитель
26c6bc7b81
Коммит
8f140b407f
|
@ -747,7 +747,6 @@ static void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
|
||||||
|
|
||||||
static int ipath_pe_intconfig(struct ipath_devdata *dd)
|
static int ipath_pe_intconfig(struct ipath_devdata *dd)
|
||||||
{
|
{
|
||||||
u64 val;
|
|
||||||
u32 chiprev;
|
u32 chiprev;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -760,9 +759,9 @@ static int ipath_pe_intconfig(struct ipath_devdata *dd)
|
||||||
if ((chiprev & INFINIPATH_R_CHIPREVMINOR_MASK) > 1) {
|
if ((chiprev & INFINIPATH_R_CHIPREVMINOR_MASK) > 1) {
|
||||||
/* Rev2+ reports extra errors via internal GPIO pins */
|
/* Rev2+ reports extra errors via internal GPIO pins */
|
||||||
dd->ipath_flags |= IPATH_GPIO_ERRINTRS;
|
dd->ipath_flags |= IPATH_GPIO_ERRINTRS;
|
||||||
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
|
dd->ipath_gpio_mask |= IPATH_GPIO_ERRINTR_MASK;
|
||||||
val |= IPATH_GPIO_ERRINTR_MASK;
|
ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
|
||||||
ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
|
dd->ipath_gpio_mask);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1056,7 +1056,7 @@ irqreturn_t ipath_intr(int irq, void *data)
|
||||||
gpiostatus &= ~(1 << IPATH_GPIO_PORT0_BIT);
|
gpiostatus &= ~(1 << IPATH_GPIO_PORT0_BIT);
|
||||||
chk0rcv = 1;
|
chk0rcv = 1;
|
||||||
}
|
}
|
||||||
if (unlikely(gpiostatus)) {
|
if (gpiostatus) {
|
||||||
/*
|
/*
|
||||||
* Some unexpected bits remain. If they could have
|
* Some unexpected bits remain. If they could have
|
||||||
* caused the interrupt, complain and clear.
|
* caused the interrupt, complain and clear.
|
||||||
|
@ -1065,9 +1065,8 @@ irqreturn_t ipath_intr(int irq, void *data)
|
||||||
* GPIO interrupts, possibly on a "three strikes"
|
* GPIO interrupts, possibly on a "three strikes"
|
||||||
* basis.
|
* basis.
|
||||||
*/
|
*/
|
||||||
u32 mask;
|
const u32 mask = (u32) dd->ipath_gpio_mask;
|
||||||
mask = ipath_read_kreg32(
|
|
||||||
dd, dd->ipath_kregs->kr_gpio_mask);
|
|
||||||
if (mask & gpiostatus) {
|
if (mask & gpiostatus) {
|
||||||
ipath_dbg("Unexpected GPIO IRQ bits %x\n",
|
ipath_dbg("Unexpected GPIO IRQ bits %x\n",
|
||||||
gpiostatus & mask);
|
gpiostatus & mask);
|
||||||
|
|
|
@ -397,6 +397,8 @@ struct ipath_devdata {
|
||||||
unsigned long ipath_pioavailshadow[8];
|
unsigned long ipath_pioavailshadow[8];
|
||||||
/* shadow of kr_gpio_out, for rmw ops */
|
/* shadow of kr_gpio_out, for rmw ops */
|
||||||
u64 ipath_gpio_out;
|
u64 ipath_gpio_out;
|
||||||
|
/* shadow the gpio mask register */
|
||||||
|
u64 ipath_gpio_mask;
|
||||||
/* kr_revision shadow */
|
/* kr_revision shadow */
|
||||||
u64 ipath_revision;
|
u64 ipath_revision;
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1387,13 +1387,12 @@ static int enable_timer(struct ipath_devdata *dd)
|
||||||
* processing.
|
* processing.
|
||||||
*/
|
*/
|
||||||
if (dd->ipath_flags & IPATH_GPIO_INTR) {
|
if (dd->ipath_flags & IPATH_GPIO_INTR) {
|
||||||
u64 val;
|
|
||||||
ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect,
|
ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect,
|
||||||
0x2074076542310ULL);
|
0x2074076542310ULL);
|
||||||
/* Enable GPIO bit 2 interrupt */
|
/* Enable GPIO bit 2 interrupt */
|
||||||
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
|
dd->ipath_gpio_mask |= (u64) (1 << IPATH_GPIO_PORT0_BIT);
|
||||||
val |= (u64) (1 << IPATH_GPIO_PORT0_BIT);
|
ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
|
||||||
ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
|
dd->ipath_gpio_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_timer(&dd->verbs_timer);
|
init_timer(&dd->verbs_timer);
|
||||||
|
@ -1412,8 +1411,9 @@ static int disable_timer(struct ipath_devdata *dd)
|
||||||
u64 val;
|
u64 val;
|
||||||
/* Disable GPIO bit 2 interrupt */
|
/* Disable GPIO bit 2 interrupt */
|
||||||
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
|
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
|
||||||
val &= ~((u64) (1 << IPATH_GPIO_PORT0_BIT));
|
dd->ipath_gpio_mask &= ~((u64) (1 << IPATH_GPIO_PORT0_BIT));
|
||||||
ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
|
ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
|
||||||
|
dd->ipath_gpio_mask);
|
||||||
/*
|
/*
|
||||||
* We might want to undo changes to debugportselect,
|
* We might want to undo changes to debugportselect,
|
||||||
* but how?
|
* but how?
|
||||||
|
|
Загрузка…
Ссылка в новой задаче