staging: qlge: Fix irq masking in INTx mode
Tracing the driver operation reveals that the INTR_EN_EN bit (per-queue interrupt control) does not immediately prevent rx completion interrupts when the device is operating in INTx mode. This leads to interrupts being raised while napi is scheduled/running. Those interrupts are ignored by qlge_isr() and falsely reported as IRQ_NONE thanks to the irq_cnt scheme. This in turn can cause frames to loiter in the receive queue until a later frame leads to another rx interrupt that will schedule napi. Use the INTR_EN_EI bit (master interrupt control) instead. Signed-off-by: Benjamin Poirier <bpoirier@suse.com> Link: https://lore.kernel.org/r/20190927101210.23856-2-bpoirier@suse.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
40115bbc40
commit
d7618e3846
|
@ -3366,6 +3366,7 @@ msi:
|
|||
}
|
||||
}
|
||||
qlge_irq_type = LEG_IRQ;
|
||||
set_bit(QL_LEGACY_ENABLED, &qdev->flags);
|
||||
netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
|
||||
"Running with legacy interrupts.\n");
|
||||
}
|
||||
|
@ -3509,6 +3510,16 @@ static void ql_resolve_queues_to_irqs(struct ql_adapter *qdev)
|
|||
intr_context->intr_dis_mask =
|
||||
INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK |
|
||||
INTR_EN_TYPE_DISABLE;
|
||||
if (test_bit(QL_LEGACY_ENABLED, &qdev->flags)) {
|
||||
/* Experience shows that when using INTx interrupts,
|
||||
* the device does not always auto-mask INTR_EN_EN.
|
||||
* Moreover, masking INTR_EN_EN manually does not
|
||||
* immediately prevent interrupt generation.
|
||||
*/
|
||||
intr_context->intr_en_mask |= INTR_EN_EI << 16 |
|
||||
INTR_EN_EI;
|
||||
intr_context->intr_dis_mask |= INTR_EN_EI << 16;
|
||||
}
|
||||
intr_context->intr_read_mask =
|
||||
INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK | INTR_EN_TYPE_READ;
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue