Skip to content

Commit

Permalink
net: make napi_disable() symmetric with enable
Browse files Browse the repository at this point in the history
Commit 3765996 ("napi: fix race inside napi_enable") fixed
an ordering bug in napi_enable() and made the napi_enable() diverge
from napi_disable(). The state transitions done on disable are
not symmetric to enable.

There is no known bug in napi_disable() this is just refactoring.

Eric suggests we can also replace msleep(1) with a more opportunistic
usleep_range().

Signed-off-by: Jakub Kicinski <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
kuba-moo authored and davem330 committed Sep 27, 2021
1 parent 930dfa5 commit 719c571
Showing 1 changed file with 12 additions and 6 deletions.
18 changes: 12 additions & 6 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -6900,19 +6900,25 @@ EXPORT_SYMBOL(netif_napi_add);

void napi_disable(struct napi_struct *n)
{
unsigned long val, new;

might_sleep();
set_bit(NAPI_STATE_DISABLE, &n->state);

while (test_and_set_bit(NAPI_STATE_SCHED, &n->state))
msleep(1);
while (test_and_set_bit(NAPI_STATE_NPSVC, &n->state))
msleep(1);
do {
val = READ_ONCE(n->state);
if (val & (NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC)) {
usleep_range(20, 200);
continue;
}

new = val | NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC;
new &= ~(NAPIF_STATE_THREADED | NAPIF_STATE_PREFER_BUSY_POLL);
} while (cmpxchg(&n->state, val, new) != val);

hrtimer_cancel(&n->timer);

clear_bit(NAPI_STATE_PREFER_BUSY_POLL, &n->state);
clear_bit(NAPI_STATE_DISABLE, &n->state);
clear_bit(NAPI_STATE_THREADED, &n->state);
}
EXPORT_SYMBOL(napi_disable);

Expand Down

0 comments on commit 719c571

Please sign in to comment.