Commit:     a0a46196cd98af5cc015842bba757571f02a8c30
Parent:     bdb95b1792664f25eb2a4d13a587d2020aa93002
Author:     David S. Miller <[EMAIL PROTECTED]>
AuthorDate: Mon Jan 7 20:35:07 2008 -0800
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Tue Jan 8 23:30:07 2008 -0800

    Create a bit to signal that a napi_disable() is in progress.
    This sets up infrastructure such that net_rx_action() can generically
    break out of the ->poll() loop on a NAPI context that has a pending
    napi_disable() yet is being bombed with packets (and thus would
    otherwise poll endlessly and not allow the napi_disable() to finish).
    Now, what napi_disable() does is first set the NAPI_STATE_DISABLE bit
    (to indicate that a disable is pending), then it polls for the
    NAPI_STATE_SCHED bit, and once the NAPI_STATE_SCHED bit is acquired
    the NAPI_STATE_DISABLE bit is cleared.  Here, the test_and_set_bit()
    provides the necessary memory barrier between the various bitops.
    napi_schedule_prep() now tests for a pending disable as it's first
    action and won't try to obtain the NAPI_STATE_SCHED bit if a disable
    is pending.
    As a result, we can remove the netif_running() check in
    netif_rx_schedule_prep() because the NAPI disable pending state serves
    this purpose.  And, it does so in a NAPI centric manner which is what
    we really want.
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
 include/linux/netdevice.h |   16 +++++++++++++---
 1 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e393995..b0813c3 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -319,21 +319,29 @@ struct napi_struct {
        NAPI_STATE_SCHED,       /* Poll is scheduled */
+       NAPI_STATE_DISABLE,     /* Disable pending */
 extern void FASTCALL(__napi_schedule(struct napi_struct *n));
+static inline int napi_disable_pending(struct napi_struct *n)
+       return test_bit(NAPI_STATE_DISABLE, &n->state);
  *     napi_schedule_prep - check if napi can be scheduled
  *     @n: napi context
  * Test if NAPI routine is already running, and if not mark
  * it as running.  This is used as a condition variable
- * insure only one NAPI poll instance runs
+ * insure only one NAPI poll instance runs.  We also make
+ * sure there is no pending NAPI disable.
 static inline int napi_schedule_prep(struct napi_struct *n)
-       return !test_and_set_bit(NAPI_STATE_SCHED, &n->state);
+       return !napi_disable_pending(n) &&
+               !test_and_set_bit(NAPI_STATE_SCHED, &n->state);
@@ -389,8 +397,10 @@ static inline void napi_complete(struct napi_struct *n)
 static inline void napi_disable(struct napi_struct *n)
+       set_bit(NAPI_STATE_DISABLE, &n->state);
        while (test_and_set_bit(NAPI_STATE_SCHED, &n->state))
+       clear_bit(NAPI_STATE_DISABLE, &n->state);
@@ -1268,7 +1278,7 @@ static inline u32 netif_msg_init(int debug_value, int 
 static inline int netif_rx_schedule_prep(struct net_device *dev,
                                         struct napi_struct *napi)
-       return netif_running(dev) && napi_schedule_prep(napi);
+       return napi_schedule_prep(napi);
 /* Add interface to tail of rx poll list. This assumes that _prep has
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at

Reply via email to