aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/devmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bpf/devmap.c')
-rw-r--r--kernel/bpf/devmap.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
index a9cd5c93dd2b..77908311ec98 100644
--- a/kernel/bpf/devmap.c
+++ b/kernel/bpf/devmap.c
@@ -232,24 +232,31 @@ static int bq_xmit_all(struct bpf_dtab_netdev *obj,
232 prefetch(xdpf); 232 prefetch(xdpf);
233 } 233 }
234 234
235 for (i = 0; i < bq->count; i++) { 235 sent = dev->netdev_ops->ndo_xdp_xmit(dev, bq->count, bq->q);
236 struct xdp_frame *xdpf = bq->q[i]; 236 if (sent < 0) {
237 int err; 237 sent = 0;
238 238 goto error;
239 err = dev->netdev_ops->ndo_xdp_xmit(dev, xdpf);
240 if (err) {
241 drops++;
242 xdp_return_frame_rx_napi(xdpf);
243 } else {
244 sent++;
245 }
246 } 239 }
240 drops = bq->count - sent;
241out:
247 bq->count = 0; 242 bq->count = 0;
248 243
249 trace_xdp_devmap_xmit(&obj->dtab->map, obj->bit, 244 trace_xdp_devmap_xmit(&obj->dtab->map, obj->bit,
250 sent, drops, bq->dev_rx, dev); 245 sent, drops, bq->dev_rx, dev);
251 bq->dev_rx = NULL; 246 bq->dev_rx = NULL;
252 return 0; 247 return 0;
248error:
249 /* If ndo_xdp_xmit fails with an errno, no frames have been
250 * xmit'ed and it's our responsibility to them free all.
251 */
252 for (i = 0; i < bq->count; i++) {
253 struct xdp_frame *xdpf = bq->q[i];
254
255 /* RX path under NAPI protection, can return frames faster */
256 xdp_return_frame_rx_napi(xdpf);
257 drops++;
258 }
259 goto out;
253} 260}
254 261
255/* __dev_map_flush is called from xdp_do_flush_map() which _must_ be signaled 262/* __dev_map_flush is called from xdp_do_flush_map() which _must_ be signaled