Message ID | 1723219138-29887-1-git-send-email-longli@linuxonhyperv.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 58a63729c957621f1990c3494c702711188ca347 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [v3,net] net: mana: Fix doorbell out of order violation and avoid unnecessary doorbell rings | expand |
Hello: This patch was applied to netdev/net.git (main) by Paolo Abeni <pabeni@redhat.com>: On Fri, 9 Aug 2024 08:58:58 -0700 you wrote: > From: Long Li <longli@microsoft.com> > > After napi_complete_done() is called when NAPI is polling in the current > process context, another NAPI may be scheduled and start running in > softirq on another CPU and may ring the doorbell before the current CPU > does. When combined with unnecessary rings when there is no need to arm > the CQ, it triggers error paths in the hardware. > > [...] Here is the summary with links: - [v3,net] net: mana: Fix doorbell out of order violation and avoid unnecessary doorbell rings https://git.kernel.org/netdev/net/c/58a63729c957 You are awesome, thank you!
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index d2f07e179e86..f83211f9e737 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -1788,7 +1788,6 @@ static void mana_poll_rx_cq(struct mana_cq *cq) static int mana_cq_handler(void *context, struct gdma_queue *gdma_queue) { struct mana_cq *cq = context; - u8 arm_bit; int w; WARN_ON_ONCE(cq->gdma_cq != gdma_queue); @@ -1799,16 +1798,23 @@ static int mana_cq_handler(void *context, struct gdma_queue *gdma_queue) mana_poll_tx_cq(cq); w = cq->work_done; - - if (w < cq->budget && - napi_complete_done(&cq->napi, w)) { - arm_bit = SET_ARM_BIT; - } else { - arm_bit = 0; + cq->work_done_since_doorbell += w; + + if (w < cq->budget) { + mana_gd_ring_cq(gdma_queue, SET_ARM_BIT); + cq->work_done_since_doorbell = 0; + napi_complete_done(&cq->napi, w); + } else if (cq->work_done_since_doorbell > + cq->gdma_cq->queue_size / COMP_ENTRY_SIZE * 4) { + /* MANA hardware requires at least one doorbell ring every 8 + * wraparounds of CQ even if there is no need to arm the CQ. + * This driver rings the doorbell as soon as we have exceeded + * 4 wraparounds. + */ + mana_gd_ring_cq(gdma_queue, 0); + cq->work_done_since_doorbell = 0; } - mana_gd_ring_cq(gdma_queue, arm_bit); - return w; } diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h index 6439fd8b437b..7caa334f4888 100644 --- a/include/net/mana/mana.h +++ b/include/net/mana/mana.h @@ -275,6 +275,7 @@ struct mana_cq { /* NAPI data */ struct napi_struct napi; int work_done; + int work_done_since_doorbell; int budget; };