net: atlantic: Implement .ndo_xdp_xmit handler
authorTaehee Yoo <ap420073@gmail.com>
Sun, 17 Apr 2022 10:12:47 +0000 (10:12 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 20 Apr 2022 09:42:57 +0000 (10:42 +0100)
aq_xdp_xmit() is the callback function of .ndo_xdp_xmit.
It internally calls aq_nic_xmit_xdpf() to send packet.

Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/aquantia/atlantic/aq_main.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.h

index e794ee2..8859586 100644 (file)
@@ -508,6 +508,7 @@ static const struct net_device_ops aq_ndev_ops = {
        .ndo_vlan_rx_kill_vid = aq_ndo_vlan_rx_kill_vid,
        .ndo_setup_tc = aq_ndo_setup_tc,
        .ndo_bpf = aq_xdp,
+       .ndo_xdp_xmit = aq_xdp_xmit,
 };
 
 static int __init aq_ndev_init_module(void)
index 9bb9b76..ea74021 100644 (file)
@@ -389,6 +389,29 @@ static void aq_rx_checksum(struct aq_ring_s *self,
                __skb_incr_checksum_unnecessary(skb);
 }
 
+int aq_xdp_xmit(struct net_device *dev, int num_frames,
+               struct xdp_frame **frames, u32 flags)
+{
+       struct aq_nic_s *aq_nic = netdev_priv(dev);
+       unsigned int vec, i, drop = 0;
+       int cpu = smp_processor_id();
+       struct aq_nic_cfg_s *aq_cfg;
+       struct aq_ring_s *ring;
+
+       aq_cfg = aq_nic_get_cfg(aq_nic);
+       vec = cpu % aq_cfg->vecs;
+       ring = aq_nic->aq_ring_tx[AQ_NIC_CFG_TCVEC2RING(aq_cfg, 0, vec)];
+
+       for (i = 0; i < num_frames; i++) {
+               struct xdp_frame *xdpf = frames[i];
+
+               if (aq_nic_xmit_xdpf(aq_nic, ring, xdpf) == NETDEV_TX_BUSY)
+                       drop++;
+       }
+
+       return num_frames - drop;
+}
+
 static struct sk_buff *aq_xdp_run_prog(struct aq_nic_s *aq_nic,
                                       struct xdp_buff *xdp,
                                       struct aq_ring_s *rx_ring,
index 52f40ea..0a6c344 100644 (file)
@@ -199,6 +199,8 @@ void aq_ring_update_queue_state(struct aq_ring_s *ring);
 void aq_ring_queue_wake(struct aq_ring_s *ring);
 void aq_ring_queue_stop(struct aq_ring_s *ring);
 bool aq_ring_tx_clean(struct aq_ring_s *self);
+int aq_xdp_xmit(struct net_device *dev, int num_frames,
+               struct xdp_frame **frames, u32 flags);
 int aq_ring_rx_clean(struct aq_ring_s *self,
                     struct napi_struct *napi,
                     int *work_done,