[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1429092351.7346.71.camel@edumazet-glaptop2.roam.corp.google.com>
Date: Wed, 15 Apr 2015 03:05:51 -0700
From: Eric Dumazet <eric.dumazet@...il.com>
To: Yuval Mintz <Yuval.Mintz@...gic.com>
Cc: David Miller <davem@...emloft.net>,
netdev <netdev@...r.kernel.org>, "bind@...s.net" <bind@...s.net>,
"peter@...leysoftware.com" <peter@...leysoftware.com>,
Ariel Elior <Ariel.Elior@...gic.com>,
Willem de Bruijn <willemb@...gle.com>
Subject: Re: [PATCH v2 net] bnx2x: Fix busy_poll vs netpoll
On Wed, 2015-04-15 at 04:05 +0000, Yuval Mintz wrote:
> > #ifdef CONFIG_NET_RX_BUSY_POLL
> > -static inline void bnx2x_fp_init_lock(struct bnx2x_fastpath *fp)
> > +
> > +enum bnx2x_fp_state {
> > + BNX2X_STATE_FP_NAPI = BIT(0), /* NAPI handler owns the queue */
> > +
> > + BNX2X_STATE_FP_NAPI_REQ_BIT = 1, /* NAPI would like to own the queue */
> > + BNX2X_STATE_FP_NAPI_REQ = BIT(1),
> > +
> > + BNX2X_STATE_FP_POLL_BIT = 2,
> > + BNX2X_STATE_FP_POLL = BIT(2), /* busy_poll owns the queue */
> > +
> > + BNX2X_STATE_FP_DISABLE_BIT = 3, /* queue is dismantled */
> > +};
>
> ...
>
> > /* called from the device poll routine to get ownership of a FP */
> > static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp)
> > {
> > + unsigned long prev, old = READ_ONCE(fp->busy_poll_state);
> > +
> > + while (1) {
> > + switch (old) {
> > + case BNX2X_STATE_FP_POLL:
> > + /* make sure bnx2x_fp_lock_poll() wont starve us */
> > + set_bit(BNX2X_STATE_FP_NAPI_REQ_BIT,
> > + &fp->busy_poll_state);
> > + /* fallthrough */
> > + case BNX2X_STATE_FP_POLL | BNX2X_STATE_FP_NAPI_REQ:
> > + return false;
> > + default:
> > + break;
> > + }
> > + prev = cmpxchg(&fp->busy_poll_state, old, BNX2X_STATE_FP_NAPI);
>
> Wouldn't this override the disabled status? Shouldn't we return 'false'
> if BNX2X_STATE_FP_DISABLE_BIT is set?
My reasoning is that at this point BNX2X_STATE_FP_DISABLE_BIT cannot be
set.
BNX2X_STATE_FP_DISABLE_BIT is set only after a call to napi_disable()
napi_disable(&bnx2x_fp(bp, i, napi));
while (!bnx2x_fp_ll_disable(&bp->fp[i]))
usleep_range(1000, 2000);
It is important to assume this, otherwise bnx2x_fp_unlock_napi() could
not be a simple write, but would need a locked operation.
Also note that napi_disable() itself sets NAPI_STATE_DISABLE
so that napi_poll() can shortcut the napi->poll() at one point
and break a potential infinite loop under rx pressure.
set_bit(NAPI_STATE_DISABLE, &n->state);
>
> > + if (unlikely(prev != old)) {
> > + old = prev;
> > + continue;
> > + }
> > + return true;
> > }
> > }
>
> BTW, this looks quite generic - isn't it possible to take it out of the
> driver and push it into the networking core, uniforming it in the process?
Yes, this is the plan I have in mind, once net-next is opened again ;)
Thanks !
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists