summaryrefslogtreecommitdiff
path: root/include/net/gro_cells.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/gro_cells.h')
-rw-r--r--include/net/gro_cells.h13
1 files changed, 11 insertions, 2 deletions
diff --git a/include/net/gro_cells.h b/include/net/gro_cells.h
index cf6c74550baa..cd856b7a11f5 100644
--- a/include/net/gro_cells.h
+++ b/include/net/gro_cells.h
@@ -19,22 +19,30 @@ static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *s
struct gro_cell *cell;
struct net_device *dev = skb->dev;
+ rcu_read_lock();
+ if (unlikely(!(dev->flags & IFF_UP)))
+ goto drop;
+
if (!gcells->cells || skb_cloned(skb) || !(dev->features & NETIF_F_GRO)) {
netif_rx(skb);
- return;
+ goto unlock;
}
cell = this_cpu_ptr(gcells->cells);
if (skb_queue_len(&cell->napi_skbs) > netdev_max_backlog) {
+drop:
atomic_long_inc(&dev->rx_dropped);
kfree_skb(skb);
- return;
+ goto unlock;
}
__skb_queue_tail(&cell->napi_skbs, skb);
if (skb_queue_len(&cell->napi_skbs) == 1)
napi_schedule(&cell->napi);
+
+unlock:
+ rcu_read_unlock();
}
/* called under BH context */
@@ -84,6 +92,7 @@ static inline void gro_cells_destroy(struct gro_cells *gcells)
for_each_possible_cpu(i) {
struct gro_cell *cell = per_cpu_ptr(gcells->cells, i);
+ napi_disable(&cell->napi);
netif_napi_del(&cell->napi);
__skb_queue_purge(&cell->napi_skbs);
}