From: Jan-Bernd Themann <ossthema@de.ibm.com>
Ok, for now I'm going to try and deal with this by reverting
the list handling to something approximating the old NAPI
code, as per the patch below.
I've only quickly test booted into this kernel on my workstation.
So take care when trying it out.
I took the liberty to add some assertions and comments all over
wrt. list and quota handling. One thing to note that (and this
was true previously too) that if ->poll() uses the whole quota
it _MUST_ _NOT_ modify the NAPI state by doing a complete or
reschedule. The net_rx_action code still owns the NAPI state in
that case, and therefore is allowed to make modifications to the
->poll_list.
I realize this adds a lot of IRQ enable/disable overhead back
into the code, but we can't get rid of that cleanly without
solving this list ownership and modification issue properly.
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 0106fa6..9837ed3 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -284,7 +284,14 @@ extern int __init netdev_boot_setup(char *str);
* Structure for NAPI scheduling similar to tasklet but with weighting
*/
struct napi_struct {
+ /* The poll_list must only be managed by the entity which
+ * changes the state of the NAPI_STATE_SCHED bit. This means
+ * whoever atomically sets that bit can add this napi_struct
+ * to the per-cpu poll_list, and whoever clears that bit
+ * can remove from the list right before clearing the bit.
+ */
struct list_head poll_list;
+
unsigned long state;
int weight;
int quota;
@@ -336,13 +343,21 @@ static inline void napi_schedule(struct napi_struct *n)
*
* Mark NAPI processing as complete.
*/
-static inline void napi_complete(struct napi_struct *n)
+static inline void __napi_complete(struct napi_struct *n)
{
BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state));
+ list_del(&n-&...