Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[sfrench/cifs-2.6.git] / kernel / bpf / devmap.c
index 15dbc15c5b0c96fb9429c797abb539abd6fcc0a5..cd8297b3bdb9518a6c3498f81a88f792ebad7f60 100644 (file)
@@ -178,6 +178,7 @@ static void dev_map_free(struct bpf_map *map)
                if (!dev)
                        continue;
 
+               free_percpu(dev->bulkq);
                dev_put(dev->dev);
                kfree(dev);
        }
@@ -273,6 +274,7 @@ void __dev_map_flush(struct bpf_map *map)
        unsigned long *bitmap = this_cpu_ptr(dtab->flush_needed);
        u32 bit;
 
+       rcu_read_lock();
        for_each_set_bit(bit, bitmap, map->max_entries) {
                struct bpf_dtab_netdev *dev = READ_ONCE(dtab->netdev_map[bit]);
                struct xdp_bulk_queue *bq;
@@ -283,11 +285,12 @@ void __dev_map_flush(struct bpf_map *map)
                if (unlikely(!dev))
                        continue;
 
-               __clear_bit(bit, bitmap);
-
                bq = this_cpu_ptr(dev->bulkq);
                bq_xmit_all(dev, bq, XDP_XMIT_FLUSH, true);
+
+               __clear_bit(bit, bitmap);
        }
+       rcu_read_unlock();
 }
 
 /* rcu_read_lock (from syscall and BPF contexts) ensures that if a delete and/or
@@ -380,6 +383,7 @@ static void dev_map_flush_old(struct bpf_dtab_netdev *dev)
 
                int cpu;
 
+               rcu_read_lock();
                for_each_online_cpu(cpu) {
                        bitmap = per_cpu_ptr(dev->dtab->flush_needed, cpu);
                        __clear_bit(dev->bit, bitmap);
@@ -387,6 +391,7 @@ static void dev_map_flush_old(struct bpf_dtab_netdev *dev)
                        bq = per_cpu_ptr(dev->bulkq, cpu);
                        bq_xmit_all(dev, bq, XDP_XMIT_FLUSH, false);
                }
+               rcu_read_unlock();
        }
 }