diff options
author | Benjamin Poirier <bpoirier@suse.com> | 2019-09-27 19:11:55 +0900 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-10-04 17:17:44 +0200 |
commit | d7618e38461e6a3f190d88fb941befd51b7c29b0 (patch) | |
tree | fe68530fecc59c73b24cf948b89cc7b5904b4d3f /drivers | |
parent | 40115bbc40e2fd2de0e01ef2a28e0d09a1b5d0d1 (diff) | |
download | linux-d7618e38461e6a3f190d88fb941befd51b7c29b0.tar.bz2 |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/qlge/qlge_main.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index 6cae33072496..d7b64d360ea8 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -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; /* |