add basic XDP support to mvneta driver
Subsystems (3)
cover add basic XDP support to mvneta driver
Add basic XDP support to mvneta driver for devices that rely on software buffer management. Currently supported verdicts are:
- XDP_DROP
- XDP_PASS
- XDP_REDIRECT
Convert mvneta driver to page_pool API.
This series is based on previous work done by Jesper and Ilias. I am currently working on XDP_TX verdict and I will add it before posting a formal series
Lorenzo Bianconi (4):
net: mvneta: introduce page pool API for sw buffer manager
net: mvneta: rely on build_skb in mvneta_rx_swbm poll routine
net: mvneta: add basic XDP support
net: mvneta: move header prefetch in mvneta_swbm_rx_frame
drivers/net/ethernet/marvell/Kconfig | 1 + drivers/net/ethernet/marvell/mvneta.c | 383 ++++++++++++++++++-------- 2 files changed, 270 insertions(+), 114 deletions(-)
Signature · 1 line
2.21.0
RFC 1/4 net: mvneta: introduce page pool API for sw buffer manager
Use the page_pool api for allocations and DMA handling instead of __dev_alloc_page()/dma_map_page() and free_page()/dma_unmap_page(). Pages are unmapped using page_pool_release_page before packets go into the network stack.
The page_pool API offers buffer recycling capabilities for XDP but allocates one page per packet, unless the driver splits and manages the allocated page.
This is a preliminary patch to add XDP support to mvneta driver
--- drivers/net/ethernet/marvell/Kconfig | 1 + drivers/net/ethernet/marvell/mvneta.c | 56 ++++++++++++++++++--------- 2 files changed, 38 insertions(+), 19 deletions(-)
drivers/net/ethernet/marvell/Kconfig +1 -0
@@ -61,6 +61,7 @@ config MVNETA depends on ARCH_MVEBU || COMPILE_TEST select MVMDIO select PHYLINK + select PAGE_POOL ---help--- This driver supports the network interface units in the Marvell ARMADA XP, ARMADA 370, ARMADA 38x and
drivers/net/ethernet/marvell/mvneta.c +37 -19
106 lines not on this page · raw message
Signature · 1 line
2.21.0
kbuild test robot
build botRe: [RFC 1/4] net: mvneta: introduce page pool API for sw buffer manager
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please…
Hi Lorenzo,
[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on net/master]
[cannot apply to v5.4-rc1 next-20191001]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
If you fix the issue, kindly add following tag
coccinelle warnings: (new ones prefixed by >>)
>> drivers/net/ethernet/marvell/mvneta.c:2841:9-16: ERROR: PTR_ERR applied after initialization to constant on line 2840
vim +2841 drivers/net/ethernet/marvell/mvneta.c
2825
2826 static int mvneta_create_page_pool(struct mvneta_port *pp,
2827 struct mvneta_rx_queue *rxq, int size)
2828 {
2829 struct page_pool_params pp_params = {
2830 .order = 0,
2831 .flags = PP_FLAG_DMA_MAP,
2832 .pool_size = size,
2833 .nid = cpu_to_node(0),
2834 .dev = pp->dev->dev.parent,
2835 .dma_dir = DMA_FROM_DEVICE,
2836 };
2837
2838 rxq->page_pool = page_pool_create(&pp_params);
2839 if (IS_ERR(rxq->page_pool)) {
> 2840 rxq->page_pool = NULL; > 2841 return PTR_ERR(rxq->page_pool);
2842 }
2843
2844 return 0;
2845 }
2846
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
RFC 2/4 net: mvneta: rely on build_skb in mvneta_rx_swbm poll routine
In reply to Lorenzo BianconiRefactor mvneta_rx_swbm code introducing mvneta_swbm_rx_frame and mvneta_swbm_add_rx_fragment routines. Rely on build_skb in oreder to allocate skb since the previous patch introduced buffer recycling using the page_pool API
--- drivers/net/ethernet/marvell/mvneta.c | 194 ++++++++++++++------------ 1 file changed, 102 insertions(+), 92 deletions(-)
drivers/net/ethernet/marvell/mvneta.c +102 -92
@@ -323,6 +323,11 @@ ETH_HLEN + ETH_FCS_LEN, \ cache_line_size()) +#define MVNETA_SKB_PAD (SKB_DATA_ALIGN(sizeof(struct skb_shared_info) + \ + NET_SKB_PAD)) +#define MVNETA_SKB_SIZE (len) (SKB_DATA_ALIGN(len) + MVNETA_SKB_PAD) +#define MVNETA_MAX_RX_BUF_SIZE (PAGE_SIZE - MVNETA_SKB_PAD) +#define IS_TSO_HEADER (txq, addr) \ ((addr >= txq->tso_hdrs_phys) && \ (addr < txq->tso_hdrs_phys + txq->size * TSO_HEADER_SIZE))
@@ -645,7 +650,6 @@ static int txq_number = 8;static int rxq_def;static int rx_copybreak__read_mostly =256 ; -static int rx_header_size__read_mostly =128 ;/* HW BM need that each port be identify by a unique ID */ static int global_port_id;
@@ -1921,30 +1925,102 @@ int mvneta_rx_refill_queue(struct mvneta_port *pp, struct mvneta_rx_queue *rxq)return i; } +static int +mvneta_swbm_rx_frame (struct mvneta_port *pp, +struct mvneta_rx_desc *rx_desc, +struct mvneta_rx_queue *rxq, +struct page *page) +{ +unsigned char *data =page_address (page); +int data_len = -MVNETA_MH_SIZE , len; +struct net_device *dev = pp->dev; +enum dma_data_direction dma_dir; + +if (MVNETA_SKB_SIZE (rx_desc->data_size) >PAGE_SIZE ) { + len =MVNETA_MAX_RX_BUF_SIZE ; + data_len += len; + }else { + len = rx_desc->data_size; + data_len += (len -ETH_FCS_LEN ); + } + + dma_dir =page_pool_get_dma_dir (rxq->page_pool); +dma_sync_single_range_for_cpu (dev->dev.parent, + rx_desc->buf_phys_addr,0 , + len, dma_dir); + + rxq->skb =build_skb (data,PAGE_SIZE ); +if (unlikely (!rxq->skb)) { +netdev_err (dev, +"Can't allocate skb on queue %d\n" , + rxq->id); + dev->stats.rx_dropped++; + rxq->skb_alloc_err++; +return -ENOMEM ; + } + +skb_reserve (rxq->skb,MVNETA_MH_SIZE +NET_SKB_PAD ); +skb_put (rxq->skb, data_len); +mvneta_rx_csum (pp, rx_desc->status, rxq->skb); + +page_pool_release_page (rxq->page_pool, page); + rxq->left_size = rx_desc->data_size - len; + rx_desc->buf_phys_addr =0 ; + +return 0 ; +} + +static void +mvneta_swbm_add_rx_fragment (struct mvneta_port *pp, +struct mvneta_rx_desc *rx_desc, +struct mvneta_rx_queue *rxq, +struct page *page) +{ +struct net_device *dev = pp->dev; +enum dma_data_direction dma_dir; +int data_len, len; + +if (rxq->left_size >MVNETA_MAX_RX_BUF_SIZE ) { + len =MVNETA_MAX_RX_BUF_SIZE ; + data_len = len; + }else { + len = rxq->left_size; + data_len = len -ETH_FCS_LEN ; + } + dma_dir =page_pool_get_dma_dir (rxq->page_pool); +dma_sync_single_range_for_cpu (dev->dev.parent, + rx_desc->buf_phys_addr,0 , + len, dma_dir); +if (data_len) { +/* refill descriptor with new buffer later */ +skb_add_rx_frag (rxq->skb, +skb_shinfo (rxq->skb)->nr_frags, + page,NET_SKB_PAD , data_len, +PAGE_SIZE ); + +page_pool_release_page (rxq->page_pool, page); + rxq->left_size -= data_len; + rx_desc->buf_phys_addr =0 ; + } +} +/* Main rx processing when using software buffer management */ static int mvneta_rx_swbm (struct napi_struct *napi,struct mvneta_port *pp,int budget,struct mvneta_rx_queue *rxq) { -struct net_device *dev = pp->dev; -int rx_todo, rx_proc; -int refill =0 ; -u32 rcvd_pkts =0 ; -u32 rcvd_bytes =0 ; +int rcvd_pkts =0 , rcvd_bytes =0 ; +int rx_todo, rx_proc =0 , refill;/* Get number of received packets */ rx_todo =mvneta_rxq_busy_desc_num_get (pp, rxq); - rx_proc =0 ;/* Fairness NAPI loop */ -while ((rcvd_pkts < budget) && (rx_proc < rx_todo)) { +while (rcvd_pkts < budget && rx_proc < rx_todo) {struct mvneta_rx_desc *rx_desc =mvneta_rxq_next_desc_get (rxq);unsigned char *data;struct page *page; -dma_addr_t phys_addr; -u32 rx_status, index; -int rx_bytes, skb_size, copy_size; -int frag_num, frag_size, frag_offset; +int index; index = rx_desc - rxq->descs; page = (struct page *)rxq->buf_virt_addr[index];
@@ -1952,98 +2028,33 @@ static int mvneta_rx_swbm(struct napi_struct *napi,/* Prefetch header */ prefetch (data); - phys_addr = rx_desc->buf_phys_addr; - rx_status = rx_desc->status; - rx_proc++; rxq->refill_num++; + rx_proc++; + +if (rx_desc->status &MVNETA_RXD_FIRST_DESC ) { +int err; -if (rx_status &MVNETA_RXD_FIRST_DESC ) {/* Check errors only for FIRST descriptor */ -if (rx_status &MVNETA_RXD_ERR_SUMMARY ) { +if (rx_desc->status &MVNETA_RXD_ERR_SUMMARY ) {mvneta_rx_error (pp, rx_desc); - dev->stats.rx_errors++; + pp->dev->stats.rx_errors++;/* leave the descriptor untouched */ continue ; } - rx_bytes = rx_desc->data_size - - (ETH_FCS_LEN +MVNETA_MH_SIZE ); -/* Allocate small skb for each new packet */ - skb_size =max (rx_copybreak, rx_header_size); - rxq->skb =netdev_alloc_skb_ip_align (dev, skb_size); -if (unlikely (!rxq->skb)) { -netdev_err (dev, -"Can't allocate skb on queue %d\n" , - rxq->id); - dev->stats.rx_dropped++; - rxq->skb_alloc_err++; + err =mvneta_swbm_rx_frame (pp, rx_desc, rxq, page); +if (err <0 )continue ; - } - copy_size =min (skb_size, rx_bytes); - -/* Copy data from buffer to SKB, skip Marvell header */ -memcpy (rxq->skb->data, data +MVNETA_MH_SIZE , - copy_size); -skb_put (rxq->skb, copy_size); - rxq->left_size = rx_bytes - copy_size; - -mvneta_rx_csum (pp, rx_status, rxq->skb); -if (rxq->left_size ==0 ) { -int size = copy_size +MVNETA_MH_SIZE ; - -dma_sync_single_range_for_cpu (dev->dev.parent, - phys_addr,0 , - size, -DMA_FROM_DEVICE ); - -/* leave the descriptor and buffer untouched */ - }else { -/* refill descriptor with new buffer later */ - rx_desc->buf_phys_addr =0 ; - - frag_num =0 ; - frag_offset = copy_size +MVNETA_MH_SIZE ; - frag_size =min (rxq->left_size, - (int )(PAGE_SIZE - frag_offset)); -skb_add_rx_frag (rxq->skb, frag_num, page, - frag_offset, frag_size, -PAGE_SIZE ); -page_pool_release_page (rxq->page_pool, page); - rxq->left_size -= frag_size; - } }else { -/* Middle or Last descriptor */ if (unlikely (!rxq->skb)) {pr_debug ("no skb for rx_status 0x%x\n" , - rx_status); + rx_desc->status);continue ; } -if (!rxq->left_size) { -/* last descriptor has only FCS */ -/* and can be discarded */ -dma_sync_single_range_for_cpu (dev->dev.parent, - phys_addr,0 , -ETH_FCS_LEN , -DMA_FROM_DEVICE ); -/* leave the descriptor and buffer untouched */ - }else { -/* refill descriptor with new buffer later */ - rx_desc->buf_phys_addr =0 ; - - frag_num =skb_shinfo (rxq->skb)->nr_frags; - frag_offset =0 ; - frag_size =min (rxq->left_size, - (int )(PAGE_SIZE - frag_offset)); -skb_add_rx_frag (rxq->skb, frag_num, page, - frag_offset, frag_size, -PAGE_SIZE ); - -page_pool_release_page (rxq->page_pool, page); - rxq->left_size -= frag_size; - } +mvneta_swbm_add_rx_fragment (pp, rx_desc, rxq, page); }/* Middle or Last descriptor */ -if (!(rx_status &MVNETA_RXD_LAST_DESC )) +if (!(rx_desc->status &MVNETA_RXD_LAST_DESC ))/* no last descriptor this time */ continue ;
@@ -2059,13 +2070,12 @@ static int mvneta_rx_swbm(struct napi_struct *napi, rcvd_bytes += rxq->skb->len;/* Linux processing */ - rxq->skb->protocol =eth_type_trans (rxq->skb, dev); + rxq->skb->protocol =eth_type_trans (rxq->skb, pp->dev);napi_gro_receive (napi, rxq->skb);/* clean uncomplete skb pointer in queue */ rxq->skb =NULL ; - rxq->left_size =0 ; }if (rcvd_pkts) {
@@ -2926,7 +2936,7 @@ static void mvneta_rxq_hw_init(struct mvneta_port *pp,/* Set Offset */ mvneta_rxq_offset_set (pp, rxq,0 );mvneta_rxq_buf_size_set (pp, rxq,PAGE_SIZE <SZ_64K ? -PAGE_SIZE : +MVNETA_MAX_RX_BUF_SIZE :MVNETA_RX_BUF_SIZE (pp->pkt_size));mvneta_rxq_bm_disable (pp, rxq);mvneta_rxq_fill (pp, rxq, rxq->size);
@@ -4636,7 +4646,7 @@ static int mvneta_probe(struct platform_device *pdev)SET_NETDEV_DEV (dev, &pdev->dev); pp->id = global_port_id++; - pp->rx_offset_correction =0 ;/* not relevant for SW BM */ + pp->rx_offset_correction =NET_SKB_PAD ;/* Obtain access to BM resources if enabled and already initialized */ bm_node =of_parse_phandle (dn,"buffer-manager" ,0 );
Signature · 1 line
2.21.0
RFC 3/4 net: mvneta: add basic XDP support
In reply to Lorenzo BianconiAdd basic XDP support to mvneta driver for devices that rely on software buffer management. Currently supported verdicts are:
- XDP_DROP
- XDP_PASS
- XDP_REDIRECT
--- drivers/net/ethernet/marvell/mvneta.c | 145 ++++++++++++++++++++++++-- 1 file changed, 136 insertions(+), 9 deletions(-)
drivers/net/ethernet/marvell/mvneta.c +136 -9
@@ -38,6 +38,7 @@#include <net/ipv6.h> #include <net/tso.h> #include <net/page_pool.h> +#include <linux/bpf_trace.h> /* Registers */ #define MVNETA_RXQ_CONFIG_REG (q) (0x1400 + ((q) << 2))
@@ -323,8 +324,10 @@ ETH_HLEN + ETH_FCS_LEN, \ cache_line_size()) +#define MVNETA_SKB_HEADROOM (max(XDP_PACKET_HEADROOM, NET_SKB_PAD) + \ + NET_IP_ALIGN)#define MVNETA_SKB_PAD (SKB_DATA_ALIGN(sizeof(struct skb_shared_info) + \ - NET_SKB_PAD)) + MVNETA_SKB_HEADROOM))#define MVNETA_SKB_SIZE (len) (SKB_DATA_ALIGN(len) + MVNETA_SKB_PAD)#define MVNETA_MAX_RX_BUF_SIZE (PAGE_SIZE - MVNETA_SKB_PAD)
@@ -352,6 +355,11 @@ struct mvneta_statistic {#define T_REG_64 64#define T_SW 1 +#define MVNETA_XDP_PASS BIT(0) +#define MVNETA_XDP_CONSUMED BIT(1) +#define MVNETA_XDP_TX BIT(2) +#define MVNETA_XDP_REDIR BIT(3) +static const struct mvneta_statistic mvneta_statistics[] = { {0x3000 ,T_REG_64 ,"good_octets_received" , }, {0x3010 ,T_REG_32 ,"good_frames_received" , },
@@ -431,6 +439,8 @@ struct mvneta_port {u32 cause_rx_tx;struct napi_struct napi; +struct bpf_prog *xdp_prog; +/* Core clock */ struct clk *clk;/* AXI clock */
@@ -611,6 +621,7 @@ struct mvneta_rx_queue {/* page_pool */ struct page_pool *page_pool; +struct xdp_rxq_info xdp_rxq;/* Virtual address of the RX buffer */ void **buf_virt_addr;
@@ -1897,6 +1908,8 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,page_pool_put_page (rxq->page_pool, data, false); } +if (xdp_rxq_info_is_reg (&rxq->xdp_rxq)) +xdp_rxq_info_unreg (&rxq->xdp_rxq);page_pool_destroy (rxq->page_pool); }
@@ -1925,16 +1938,52 @@ int mvneta_rx_refill_queue(struct mvneta_port *pp, struct mvneta_rx_queue *rxq)return i; } +static int +mvneta_run_xdp (struct mvneta_port *pp,struct bpf_prog *prog, +struct xdp_buff *xdp) +{ +u32 ret =bpf_prog_run_xdp (prog, xdp); +int err; + +switch (ret) { +case XDP_PASS : +return MVNETA_XDP_PASS ; +case XDP_REDIRECT : + err =xdp_do_redirect (pp->dev, xdp, prog); +if (err) { +xdp_return_buff (xdp); +return MVNETA_XDP_CONSUMED ; + } +return MVNETA_XDP_REDIR ; +default : +bpf_warn_invalid_xdp_action (ret); +/* fall through */ +case XDP_ABORTED : +trace_xdp_exception (pp->dev, prog, ret); +/* fall through */ +case XDP_DROP : +xdp_return_buff (xdp); +return MVNETA_XDP_CONSUMED ; + } +} +static int mvneta_swbm_rx_frame (struct mvneta_port *pp,struct mvneta_rx_desc *rx_desc,struct mvneta_rx_queue *rxq, +struct bpf_prog *xdp_prog,struct page *page) {unsigned char *data =page_address (page);int data_len = -MVNETA_MH_SIZE , len;struct net_device *dev = pp->dev;enum dma_data_direction dma_dir; +struct xdp_buff xdp = { + .data_hard_start = data, + .data = data +MVNETA_SKB_HEADROOM , + .rxq = &rxq->xdp_rxq, + }; +xdp_set_data_meta_invalid (&xdp);if (MVNETA_SKB_SIZE (rx_desc->data_size) >PAGE_SIZE ) { len =MVNETA_MAX_RX_BUF_SIZE ;
@@ -1943,13 +1992,24 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp, len = rx_desc->data_size; data_len += (len -ETH_FCS_LEN ); } + xdp.data_end = xdp.data + data_len; dma_dir =page_pool_get_dma_dir (rxq->page_pool);dma_sync_single_range_for_cpu (dev->dev.parent, rx_desc->buf_phys_addr,0 , len, dma_dir); - rxq->skb =build_skb (data,PAGE_SIZE ); +if (xdp_prog) { +int ret; + + ret =mvneta_run_xdp (pp, xdp_prog, &xdp); +if (ret !=MVNETA_XDP_PASS ) { + rx_desc->buf_phys_addr =0 ; +return -EAGAIN ; + } + } + + rxq->skb =build_skb (xdp.data_hard_start,PAGE_SIZE );if (unlikely (!rxq->skb)) { netdev_err(dev, "Can't allocate skb on queue %d\n",
@@ -1959,8 +2019,9 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp,return -ENOMEM ; } -skb_reserve (rxq->skb,MVNETA_MH_SIZE +NET_SKB_PAD ); -skb_put (rxq->skb, data_len); +skb_reserve (rxq->skb, +MVNETA_MH_SIZE + xdp.data - xdp.data_hard_start); +skb_put (rxq->skb, xdp.data_end - xdp.data);mvneta_rx_csum (pp, rx_desc->status, rxq->skb);page_pool_release_page (rxq->page_pool, page);
@@ -1995,7 +2056,7 @@ mvneta_swbm_add_rx_fragment(struct mvneta_port *pp,/* refill descriptor with new buffer later */ skb_add_rx_frag (rxq->skb,skb_shinfo (rxq->skb)->nr_frags, - page,NET_SKB_PAD , data_len, + page,MVNETA_SKB_HEADROOM , data_len,PAGE_SIZE );page_pool_release_page (rxq->page_pool, page);
@@ -2011,10 +2072,14 @@ static int mvneta_rx_swbm(struct napi_struct *napi, {int rcvd_pkts =0 , rcvd_bytes =0 ;int rx_todo, rx_proc =0 , refill; +struct bpf_prog *xdp_prog;/* Get number of received packets */ rx_todo =mvneta_rxq_busy_desc_num_get (pp, rxq); +rcu_read_lock (); + xdp_prog =READ_ONCE (pp->xdp_prog); +/* Fairness NAPI loop */ while (rcvd_pkts < budget && rx_proc < rx_todo) {struct mvneta_rx_desc *rx_desc =mvneta_rxq_next_desc_get (rxq);
@@ -2029,6 +2094,7 @@ static int mvneta_rx_swbm(struct napi_struct *napi,prefetch (data); rxq->refill_num++; + rcvd_pkts++; rx_proc++;if (rx_desc->status &MVNETA_RXD_FIRST_DESC ) {
@@ -2042,7 +2108,8 @@ static int mvneta_rx_swbm(struct napi_struct *napi,continue ; } - err =mvneta_swbm_rx_frame (pp, rx_desc, rxq, page); + err =mvneta_swbm_rx_frame (pp, rx_desc, rxq, + xdp_prog, page);if (err <0 )continue ; }else {
@@ -2066,7 +2133,6 @@ static int mvneta_rx_swbm(struct napi_struct *napi, rxq->skb =NULL ;continue ; } - rcvd_pkts++; rcvd_bytes += rxq->skb->len;/* Linux processing */
@@ -2077,6 +2143,7 @@ static int mvneta_rx_swbm(struct napi_struct *napi,/* clean uncomplete skb pointer in queue */ rxq->skb =NULL ; } +rcu_read_unlock ();if (rcvd_pkts) {struct mvneta_pcpu_stats *stats =this_cpu_ptr (pp->stats);
@@ -2836,14 +2903,16 @@ static int mvneta_poll(struct napi_struct *napi, int budget)static int mvneta_create_page_pool (struct mvneta_port *pp,struct mvneta_rx_queue *rxq,int size) { +struct bpf_prog *xdp_prog =READ_ONCE (pp->xdp_prog);struct page_pool_params pp_params = { .order =0 , .flags =PP_FLAG_DMA_MAP , .pool_size = size, .nid =cpu_to_node (0 ), .dev = pp->dev->dev.parent, - .dma_dir =DMA_FROM_DEVICE , + .dma_dir = xdp_prog ?DMA_BIDIRECTIONAL :DMA_FROM_DEVICE , }; +int err; rxq->page_pool =page_pool_create (&pp_params);if (IS_ERR (rxq->page_pool)) {
@@ -2851,7 +2920,22 @@ static int mvneta_create_page_pool(struct mvneta_port *pp,return PTR_ERR (rxq->page_pool); } + err =xdp_rxq_info_reg (&rxq->xdp_rxq, pp->dev,0 ); +if (err <0 ) + goto err_free_pp; + + err =xdp_rxq_info_reg_mem_model (&rxq->xdp_rxq,MEM_TYPE_PAGE_POOL , + rxq->page_pool); +if (err) + goto err_unregister_pp; +return 0 ; + +err_unregister_pp: +xdp_rxq_info_unreg (&rxq->xdp_rxq); +err_free_pp: +page_pool_destroy (rxq->page_pool); +return err; }/* Handle rxq fill: allocates rxq skbs; called when initializing a port */
@@ -3291,6 +3375,11 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) mtu =ALIGN (MVNETA_RX_PKT_SIZE (mtu),8 ); } +if (pp->xdp_prog && mtu >MVNETA_MAX_RX_BUF_SIZE ) { +netdev_info (dev,"Illegal MTU value %d for XDP mode\n" , mtu); +return -EINVAL ; + } + dev->mtu = mtu;if (!netif_running (dev)) {
@@ -3960,6 +4049,43 @@ static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)return phylink_mii_ioctl (pp->phylink, ifr, cmd); } +static int mvneta_xdp_setup (struct net_device *dev,struct bpf_prog *prog, +struct netlink_ext_ack *extack) +{ +struct mvneta_port *pp =netdev_priv (dev); +struct bpf_prog *old_prog; + +if (prog && dev->mtu >MVNETA_MAX_RX_BUF_SIZE ) { +NL_SET_ERR_MSG_MOD (extack,"Jumbo frames not supported on XDP" ); +return -EOPNOTSUPP ; + } + +mvneta_stop (dev); + + old_prog =xchg (&pp->xdp_prog, prog); +if (old_prog) +bpf_prog_put (old_prog); + +mvneta_open (dev); + +return 0 ; +} + +static int mvneta_xdp (struct net_device *dev,struct netdev_bpf *xdp) +{ +struct mvneta_port *pp =netdev_priv (dev); + +switch (xdp->command) { +case XDP_SETUP_PROG : +return mvneta_xdp_setup (dev, xdp->prog, xdp->extack); +case XDP_QUERY_PROG : + xdp->prog_id = pp->xdp_prog ? pp->xdp_prog->aux->id :0 ; +return 0 ; +default : +return -EINVAL ; + } +} +/* Ethtool methods */ /* Set link ksettings (phy address, speed) for ethtools */
@@ -4356,6 +4482,7 @@ static const struct net_device_ops mvneta_netdev_ops = { .ndo_fix_features = mvneta_fix_features, .ndo_get_stats64 = mvneta_get_stats64, .ndo_do_ioctl = mvneta_ioctl, + .ndo_bpf = mvneta_xdp, };static const struct ethtool_ops mvneta_eth_tool_ops = {
@@ -4646,7 +4773,7 @@ static int mvneta_probe(struct platform_device *pdev)SET_NETDEV_DEV (dev, &pdev->dev); pp->id = global_port_id++; - pp->rx_offset_correction =NET_SKB_PAD ; + pp->rx_offset_correction =MVNETA_SKB_HEADROOM ;/* Obtain access to BM resources if enabled and already initialized */ bm_node =of_parse_phandle (dn,"buffer-manager" ,0 );
Signature · 1 line
2.21.0
Re: [RFC 3/4] net: mvneta: add basic XDP support
drivers/net/ethernet/marvell/mvneta.c static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) · line 4060
Quoted 11 lines · On Tue, 1 Oct 2019 11:24:43 +0200 Lorenzo Bianconi <[email protected]> wrote:
+static int mvneta_xdp_setup(struct
net_device*dev, structbpf_prog*prog,drivers/net/ethernet/marvell/mvneta.c +7
-0+ struct netlink_ext_ack *extack) +{ +struct mvneta_port *pp =netdev_priv (dev); +struct bpf_prog *old_prog; + +if (prog && dev->mtu >MVNETA_MAX_RX_BUF_SIZE ) { + NL_SET_ERR_MSG_MOD(extack, "Jumbo frames notsupported on XDP");
drivers/net/ethernet/marvell/mvneta.c +1
-0+return -EOPNOTSUPP ;
-ENOTSUPP maybe?
drivers/net/ethernet/marvell/mvneta.c static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) · line 4063
Quoted 3 lines
drivers/net/ethernet/marvell/mvneta.c +3
-0+ } + +mvneta_stop (dev);
only stop and restart if already running
drivers/net/ethernet/marvell/mvneta.c static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) · line 4069
Quoted 6 lines
drivers/net/ethernet/marvell/mvneta.c +6
-0+ + old_prog =xchg (&pp->xdp_prog, prog); +if (old_prog) +bpf_prog_put (old_prog); + +mvneta_open (dev);
^^
Signature · 2 lines
Matteo Croce per aspera ad upstream
Re: [RFC 3/4] net: mvneta: add basic XDP support
Quoted 15 lines · Matteo Croce
drivers/net/ethernet/marvell/mvneta.c static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) · line 4060
Quoted 11 lines · On Tue, 1 Oct 2019 11:24:43 +0200 Lorenzo Bianconi <[email protected]> wrote:
+static int mvneta_xdp_setup(struct
net_device*dev, structbpf_prog*prog,drivers/net/ethernet/marvell/mvneta.c +7
-0+ struct netlink_ext_ack *extack) +{ +struct mvneta_port *pp =netdev_priv (dev); +struct bpf_prog *old_prog; + +if (prog && dev->mtu >MVNETA_MAX_RX_BUF_SIZE ) { + NL_SET_ERR_MSG_MOD(extack, "Jumbo frames notsupported on XDP");
drivers/net/ethernet/marvell/mvneta.c +1
-0+return -EOPNOTSUPP ;
-ENOTSUPPmaybe?
No, ENOTSUPP is NFS-specific, and defined in a non-UAPI header; the correct one to use is EOPNOTSUPP :)
-Toke
Re: [RFC 3/4] net: mvneta: add basic XDP support
In reply to Lorenzo BianconiQuoted 5 lines · On Tue, 1 Oct 2019 11:24:43 +0200 Lorenzo Bianconi <[email protected]> wrote:
Add basic XDP support to mvneta driver for devices that rely on software buffer management. Currently supported verdicts are:
-XDP_DROP
-XDP_PASS
-XDP_REDIRECT
You're supporting XDP_ABORTED as well :P any plans for XDP_TX?
Quoted 128 lines
Signed-off-by Lorenzo Bianconi <[email protected]>--- drivers/net/ethernet/marvell/mvneta.c | 145 ++++++++++++++++++++++++-- 1 file changed, 136 insertions(+), 9 deletions(-)drivers/net/ethernet/marvell/mvneta.c +51
-1@@ -38,6 +38,7 @@#include <net/ipv6.h> #include <net/tso.h> #include <net/page_pool.h> +#include <linux/bpf_trace.h> /* Registers */ #define MVNETA_RXQ_CONFIG_REG (q) (0x1400 + ((q) << 2))@@ -323,8 +324,10 @@ ETH_HLEN + ETH_FCS_LEN, \ cache_line_size()) +#define MVNETA_SKB_HEADROOM (max(XDP_PACKET_HEADROOM, NET_SKB_PAD) + \ + NET_IP_ALIGN)#define MVNETA_SKB_PAD (SKB_DATA_ALIGN(sizeof(struct skb_shared_info) + \ - NET_SKB_PAD)) + MVNETA_SKB_HEADROOM))#define MVNETA_SKB_SIZE (len) (SKB_DATA_ALIGN(len) + MVNETA_SKB_PAD)#define MVNETA_MAX_RX_BUF_SIZE (PAGE_SIZE - MVNETA_SKB_PAD)@@ -352,6 +355,11 @@ struct mvneta_statistic {#define T_REG_64 64#define T_SW 1 +#define MVNETA_XDP_PASS BIT(0) +#define MVNETA_XDP_CONSUMED BIT(1) +#define MVNETA_XDP_TX BIT(2) +#define MVNETA_XDP_REDIR BIT(3) +static const struct mvneta_statistic mvneta_statistics[] = { {0x3000 ,T_REG_64 ,"good_octets_received" , }, {0x3010 ,T_REG_32 ,"good_frames_received" , },@@ -431,6 +439,8 @@ struct mvneta_port {u32 cause_rx_tx;struct napi_struct napi; +struct bpf_prog *xdp_prog; +/* Core clock */ struct clk *clk;/* AXI clock */ @@ -611,6 +621,7 @@ struct mvneta_rx_queue {/* page_pool */ struct page_pool *page_pool; +struct xdp_rxq_info xdp_rxq;/* Virtual address of the RX buffer */ void **buf_virt_addr;@@ -1897,6 +1908,8 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,page_pool_put_page (rxq->page_pool, data, false); } +if (xdp_rxq_info_is_reg (&rxq->xdp_rxq)) +xdp_rxq_info_unreg (&rxq->xdp_rxq);page_pool_destroy (rxq->page_pool); }@@ -1925,16 +1938,52 @@ int mvneta_rx_refill_queue(struct mvneta_port *pp, struct mvneta_rx_queue *rxq)return i; } +static int +mvneta_run_xdp (struct mvneta_port *pp,struct bpf_prog *prog, +struct xdp_buff *xdp) +{ +u32 ret =bpf_prog_run_xdp (prog, xdp); +int err; + +switch (ret) { +case XDP_PASS : +return MVNETA_XDP_PASS ; +case XDP_REDIRECT : + err =xdp_do_redirect (pp->dev, xdp, prog); +if (err) { +xdp_return_buff (xdp); +return MVNETA_XDP_CONSUMED ; + } +return MVNETA_XDP_REDIR ; +default : +bpf_warn_invalid_xdp_action (ret); +/* fall through */ +case XDP_ABORTED : +trace_xdp_exception (pp->dev, prog, ret); +/* fall through */ +case XDP_DROP : +xdp_return_buff (xdp); +return MVNETA_XDP_CONSUMED ; + } +} +static int mvneta_swbm_rx_frame (struct mvneta_port *pp,struct mvneta_rx_desc *rx_desc,struct mvneta_rx_queue *rxq, +struct bpf_prog *xdp_prog,struct page *page) {unsigned char *data =page_address (page);int data_len = -MVNETA_MH_SIZE , len;struct net_device *dev = pp->dev;enum dma_data_direction dma_dir; +struct xdp_buff xdp = { + .data_hard_start = data, + .data = data +MVNETA_SKB_HEADROOM , + .rxq = &rxq->xdp_rxq, + }; +xdp_set_data_meta_invalid (&xdp);if (MVNETA_SKB_SIZE (rx_desc->data_size) >PAGE_SIZE ) { len =MVNETA_MAX_RX_BUF_SIZE ;@@ -1943,13 +1992,24 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp, len = rx_desc->data_size; data_len += (len -ETH_FCS_LEN ); } + xdp.data_end = xdp.data + data_len; dma_dir =page_pool_get_dma_dir (rxq->page_pool);
drivers/net/ethernet/marvell/mvneta.c mvneta_swbm_rx_frame(struct mvneta_port *pp, · line 2006
Quoted 10 lines
drivers/net/ethernet/marvell/mvneta.c +5
-1dma_sync_single_range_for_cpu (dev->dev.parent, rx_desc->buf_phys_addr,0 , len, dma_dir); - rxq->skb =build_skb (data,PAGE_SIZE ); +if (xdp_prog) { +int ret; + + ret =mvneta_run_xdp (pp, xdp_prog, &xdp); +if (ret !=MVNETA_XDP_PASS ) {
Nit: you could have it written as:
if (mvneta_run_xdp(...)) {
//blah
}since MVNETA_XDP_PASS is 0. The 'ret' variable is not needed here.
Quoted 99 lines
drivers/net/ethernet/marvell/mvneta.c +21
-6+ rx_desc->buf_phys_addr =0 ; +return -EAGAIN ; + } + } + + rxq->skb =build_skb (xdp.data_hard_start,PAGE_SIZE );if (unlikely (!rxq->skb)) { netdev_err(dev, "Can't allocate skb on queue %d\n",@@ -1959,8 +2019,9 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp,return -ENOMEM ; } -skb_reserve (rxq->skb,MVNETA_MH_SIZE +NET_SKB_PAD ); -skb_put (rxq->skb, data_len); +skb_reserve (rxq->skb, +MVNETA_MH_SIZE + xdp.data - xdp.data_hard_start); +skb_put (rxq->skb, xdp.data_end - xdp.data);mvneta_rx_csum (pp, rx_desc->status, rxq->skb);page_pool_release_page (rxq->page_pool, page);@@ -1995,7 +2056,7 @@ mvneta_swbm_add_rx_fragment(struct mvneta_port *pp,/* refill descriptor with new buffer later */ skb_add_rx_frag (rxq->skb,skb_shinfo (rxq->skb)->nr_frags, - page,NET_SKB_PAD , data_len, + page,MVNETA_SKB_HEADROOM , data_len,PAGE_SIZE );page_pool_release_page (rxq->page_pool, page);@@ -2011,10 +2072,14 @@ static int mvneta_rx_swbm(struct napi_struct *napi, {int rcvd_pkts =0 , rcvd_bytes =0 ;int rx_todo, rx_proc =0 , refill; +struct bpf_prog *xdp_prog;/* Get number of received packets */ rx_todo =mvneta_rxq_busy_desc_num_get (pp, rxq); +rcu_read_lock (); + xdp_prog =READ_ONCE (pp->xdp_prog); +/* Fairness NAPI loop */ while (rcvd_pkts < budget && rx_proc < rx_todo) {struct mvneta_rx_desc *rx_desc =mvneta_rxq_next_desc_get (rxq);@@ -2029,6 +2094,7 @@ static int mvneta_rx_swbm(struct napi_struct *napi,prefetch (data); rxq->refill_num++; + rcvd_pkts++; rx_proc++;if (rx_desc->status &MVNETA_RXD_FIRST_DESC ) {@@ -2042,7 +2108,8 @@ static int mvneta_rx_swbm(struct napi_struct *napi,continue ; } - err =mvneta_swbm_rx_frame (pp, rx_desc, rxq, page); + err =mvneta_swbm_rx_frame (pp, rx_desc, rxq, + xdp_prog, page);if (err <0 )continue ; }else {@@ -2066,7 +2133,6 @@ static int mvneta_rx_swbm(struct napi_struct *napi, rxq->skb =NULL ;continue ; } - rcvd_pkts++; rcvd_bytes += rxq->skb->len;/* Linux processing */ @@ -2077,6 +2143,7 @@ static int mvneta_rx_swbm(struct napi_struct *napi,/* clean uncomplete skb pointer in queue */ rxq->skb =NULL ; } +rcu_read_unlock ();if (rcvd_pkts) {struct mvneta_pcpu_stats *stats =this_cpu_ptr (pp->stats);@@ -2836,14 +2903,16 @@ static int mvneta_poll(struct napi_struct *napi, int budget)static int mvneta_create_page_pool (struct mvneta_port *pp,struct mvneta_rx_queue *rxq,int size) { +struct bpf_prog *xdp_prog =READ_ONCE (pp->xdp_prog);struct page_pool_params pp_params = { .order =0 , .flags =PP_FLAG_DMA_MAP , .pool_size = size, .nid =cpu_to_node (0 ), .dev = pp->dev->dev.parent, - .dma_dir =DMA_FROM_DEVICE , + .dma_dir = xdp_prog ?DMA_BIDIRECTIONAL :DMA_FROM_DEVICE , }; +int err; rxq->page_pool =page_pool_create (&pp_params);if (IS_ERR (rxq->page_pool)) {@@ -2851,7 +2920,22 @@ static int mvneta_create_page_pool(struct mvneta_port *pp,return PTR_ERR (rxq->page_pool);
drivers/net/ethernet/marvell/mvneta.c static int mvneta_create_page_pool(struct mvneta_port *pp, · line 2930
Quoted 10 lines
drivers/net/ethernet/marvell/mvneta.c +8
-0} + err =xdp_rxq_info_reg (&rxq->xdp_rxq, pp->dev,0 ); +if (err <0 ) + goto err_free_pp; + + err =xdp_rxq_info_reg_mem_model (&rxq->xdp_rxq,MEM_TYPE_PAGE_POOL , + rxq->page_pool); +if (err) + goto err_unregister_pp;
err_unregister_rxq?
Quoted 50 lines
drivers/net/ethernet/marvell/mvneta.c +35
-0+return 0 ; + +err_unregister_pp: +xdp_rxq_info_unreg (&rxq->xdp_rxq); +err_free_pp: +page_pool_destroy (rxq->page_pool); +return err; }/* Handle rxq fill: allocates rxq skbs; called when initializing a port */ @@ -3291,6 +3375,11 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) mtu =ALIGN (MVNETA_RX_PKT_SIZE (mtu),8 ); } +if (pp->xdp_prog && mtu >MVNETA_MAX_RX_BUF_SIZE ) { +netdev_info (dev,"Illegal MTU value %d for XDP mode\n" , mtu); +return -EINVAL ; + } + dev->mtu = mtu;if (!netif_running (dev)) {@@ -3960,6 +4049,43 @@ static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)return phylink_mii_ioctl (pp->phylink, ifr, cmd); } +static int mvneta_xdp_setup (struct net_device *dev,struct bpf_prog *prog, +struct netlink_ext_ack *extack) +{ +struct mvneta_port *pp =netdev_priv (dev); +struct bpf_prog *old_prog; + +if (prog && dev->mtu >MVNETA_MAX_RX_BUF_SIZE ) { +NL_SET_ERR_MSG_MOD (extack,"Jumbo frames not supported on XDP" ); +return -EOPNOTSUPP ; + } + +mvneta_stop (dev); + + old_prog =xchg (&pp->xdp_prog, prog); +if (old_prog) +bpf_prog_put (old_prog); + +mvneta_open (dev); + +return 0 ; +} + +static int mvneta_xdp (struct net_device *dev,struct netdev_bpf *xdp)
drivers/net/ethernet/marvell/mvneta.c static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) · line 4084
Quoted 10 lines
drivers/net/ethernet/marvell/mvneta.c +10
-0+{ +struct mvneta_port *pp =netdev_priv (dev); + +switch (xdp->command) { +case XDP_SETUP_PROG : +return mvneta_xdp_setup (dev, xdp->prog, xdp->extack); +case XDP_QUERY_PROG : + xdp->prog_id = pp->xdp_prog ? pp->xdp_prog->aux->id :0 ; +return 0 ; +default :
NL_SET_ERR_MSG_MOD(xdp->extack, "Unknown XDP command"); ?
Quoted 24 lines
drivers/net/ethernet/marvell/mvneta.c +6
-1+return -EINVAL ; + } +} +/* Ethtool methods */ /* Set link ksettings (phy address, speed) for ethtools */ @@ -4356,6 +4482,7 @@ static const struct net_device_ops mvneta_netdev_ops = { .ndo_fix_features = mvneta_fix_features, .ndo_get_stats64 = mvneta_get_stats64, .ndo_do_ioctl = mvneta_ioctl, + .ndo_bpf = mvneta_xdp, };static const struct ethtool_ops mvneta_eth_tool_ops = {@@ -4646,7 +4773,7 @@ static int mvneta_probe(struct platform_device *pdev)SET_NETDEV_DEV (dev, &pdev->dev); pp->id = global_port_id++; - pp->rx_offset_correction =NET_SKB_PAD ; + pp->rx_offset_correction =MVNETA_SKB_HEADROOM ;/* Obtain access to BM resources if enabled and already initialized */ bm_node =of_parse_phandle (dn,"buffer-manager" ,0 );
Re: [RFC 3/4] net: mvneta: add basic XDP support
Quoted 10 lines · Maciej Fijalkowski
Quoted 5 lines · On Tue, 1 Oct 2019 11:24:43 +0200 Lorenzo Bianconi <[email protected]> wrote:
Add basic XDP support to mvneta driver for devices that rely on software buffer management. Currently supported verdicts are:
-XDP_DROP
-XDP_PASS
-XDP_REDIRECTYou're supporting
XDP_ABORTEDas well :P any plans forXDP_TX?
Wait, if you are supporting REDIRECT but not TX, that means redirect only works to other, non-mvneta, devices, right? Maybe that should be made clear in the commit message :)
-Toke
Re: [RFC 3/4] net: mvneta: add basic XDP support
Quoted 11 lines · On Tue, 01 Oct 2019 13:06:36 +0200 Toke Høiland-Jørgensen <[email protected]>…
Quoted 9 lines · Maciej Fijalkowski
Quoted 5 lines · On Tue, 1 Oct 2019 11:24:43 +0200 Lorenzo Bianconi <[email protected]> wrote:
Add basic XDP support to mvneta driver for devices that rely on software buffer management. Currently supported verdicts are:
-XDP_DROP
-XDP_PASS
-XDP_REDIRECT
Quoted 5 lines
Quoted 1 line
You're supporting
XDP_ABORTEDas well :P any plans forXDP_TX?Wait, if you are supporting REDIRECT but not TX, that means redirect only works to other, non-mvneta, devices, right? Maybe that should be made clear in the commit message :)
If you implemented XDP_REDIRECT, then it should be trivial to implement XDP_TX, as you can just convert the xdp_buff to xdp_frame and call your ndo_xdp_xmit function directly (and do the tail-flush).
Or maybe you are missing a ndo_xdp_xmit function (as Toke indirectly points out).
Signature · 4 lines
Best regards, Jesper Dangaard Brouer MSc.CS, Principal Kernel Engineer at Red Hat LinkedIn: http://www.linkedin.com/in/brouer
Re: [RFC 3/4] net: mvneta: add basic XDP support
Quoted 20 lines
Quoted 11 lines · On Tue, 01 Oct 2019 13:06:36 +0200 Toke Høiland-Jørgensen <[email protected]>…
Quoted 9 lines · Maciej Fijalkowski
Quoted 5 lines · On Tue, 1 Oct 2019 11:24:43 +0200 Lorenzo Bianconi <[email protected]> wrote:
Add basic XDP support to mvneta driver for devices that rely on software buffer management. Currently supported verdicts are:
-XDP_DROP
-XDP_PASS
-XDP_REDIRECTQuoted 5 lines
Quoted 1 line
You're supporting
XDP_ABORTEDas well :P any plans forXDP_TX?Wait, if you are supporting REDIRECT but not TX, that means redirect only works to other, non-mvneta, devices, right? Maybe that should be made clear in the commit message :)
Quoted 6 lines
If you implemented
XDP_REDIRECT, then it should be trivial to implementXDP_TX, as you can just convert thexdp_bufftoxdp_frameand call yourndo_xdp_xmitfunction directly (and do the tail-flush).Or maybe you are missing a
ndo_xdp_xmitfunction (as Toke indirectly points out).
Hi Jesper and Toke,
my plan is to add XDP_TX before posting a formal series (I am working on it). I shared this RFC series to get some comments and share the current status.
Regards,
Lorenzo
Quoted 6 lines
Signature · 5 lines
-- Best regards, Jesper Dangaard Brouer MSc.CS, Principal Kernel Engineer at Red Hat LinkedIn: http://www.linkedin.com/in/brouer
Re: [RFC 3/4] net: mvneta: add basic XDP support
In reply to Maciej FijalkowskiQuoted 10 lines
Quoted 5 lines · On Tue, 1 Oct 2019 11:24:43 +0200 Lorenzo Bianconi <[email protected]> wrote:
Add basic XDP support to mvneta driver for devices that rely on software buffer management. Currently supported verdicts are:
-XDP_DROP
-XDP_PASS
-XDP_REDIRECTYou're supporting
XDP_ABORTEDas well :P any plans forXDP_TX?
Hi Maciej,
yes, I am currently working on XDP_TX and I will add it before posting a formal series
Regards,
Lorenzo
Quoted 347 lines
Quoted 129 lines
Signed-off-by Lorenzo Bianconi <[email protected]>--- drivers/net/ethernet/marvell/mvneta.c | 145 ++++++++++++++++++++++++-- 1 file changed, 136 insertions(+), 9 deletions(-)drivers/net/ethernet/marvell/mvneta.c +51
-1@@ -38,6 +38,7 @@#include <net/ipv6.h> #include <net/tso.h> #include <net/page_pool.h> +#include <linux/bpf_trace.h> /* Registers */ #define MVNETA_RXQ_CONFIG_REG (q) (0x1400 + ((q) << 2))@@ -323,8 +324,10 @@ ETH_HLEN + ETH_FCS_LEN, \ cache_line_size()) +#define MVNETA_SKB_HEADROOM (max(XDP_PACKET_HEADROOM, NET_SKB_PAD) + \ + NET_IP_ALIGN)#define MVNETA_SKB_PAD (SKB_DATA_ALIGN(sizeof(struct skb_shared_info) + \ - NET_SKB_PAD)) + MVNETA_SKB_HEADROOM))#define MVNETA_SKB_SIZE (len) (SKB_DATA_ALIGN(len) + MVNETA_SKB_PAD)#define MVNETA_MAX_RX_BUF_SIZE (PAGE_SIZE - MVNETA_SKB_PAD)@@ -352,6 +355,11 @@ struct mvneta_statistic {#define T_REG_64 64#define T_SW 1 +#define MVNETA_XDP_PASS BIT(0) +#define MVNETA_XDP_CONSUMED BIT(1) +#define MVNETA_XDP_TX BIT(2) +#define MVNETA_XDP_REDIR BIT(3) +static const struct mvneta_statistic mvneta_statistics[] = { {0x3000 ,T_REG_64 ,"good_octets_received" , }, {0x3010 ,T_REG_32 ,"good_frames_received" , },@@ -431,6 +439,8 @@ struct mvneta_port {u32 cause_rx_tx;struct napi_struct napi; +struct bpf_prog *xdp_prog; +/* Core clock */ struct clk *clk;/* AXI clock */ @@ -611,6 +621,7 @@ struct mvneta_rx_queue {/* page_pool */ struct page_pool *page_pool; +struct xdp_rxq_info xdp_rxq;/* Virtual address of the RX buffer */ void **buf_virt_addr;@@ -1897,6 +1908,8 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,page_pool_put_page (rxq->page_pool, data, false); } +if (xdp_rxq_info_is_reg (&rxq->xdp_rxq)) +xdp_rxq_info_unreg (&rxq->xdp_rxq);page_pool_destroy (rxq->page_pool); }@@ -1925,16 +1938,52 @@ int mvneta_rx_refill_queue(struct mvneta_port *pp, struct mvneta_rx_queue *rxq)return i; } +static int +mvneta_run_xdp (struct mvneta_port *pp,struct bpf_prog *prog, +struct xdp_buff *xdp) +{ +u32 ret =bpf_prog_run_xdp (prog, xdp); +int err; + +switch (ret) { +case XDP_PASS : +return MVNETA_XDP_PASS ; +case XDP_REDIRECT : + err =xdp_do_redirect (pp->dev, xdp, prog); +if (err) { +xdp_return_buff (xdp); +return MVNETA_XDP_CONSUMED ; + } +return MVNETA_XDP_REDIR ; +default : +bpf_warn_invalid_xdp_action (ret); +/* fall through */ +case XDP_ABORTED : +trace_xdp_exception (pp->dev, prog, ret); +/* fall through */ +case XDP_DROP : +xdp_return_buff (xdp); +return MVNETA_XDP_CONSUMED ; + } +} +static int mvneta_swbm_rx_frame (struct mvneta_port *pp,struct mvneta_rx_desc *rx_desc,struct mvneta_rx_queue *rxq, +struct bpf_prog *xdp_prog,struct page *page) {unsigned char *data =page_address (page);int data_len = -MVNETA_MH_SIZE , len;struct net_device *dev = pp->dev;enum dma_data_direction dma_dir; +struct xdp_buff xdp = { + .data_hard_start = data, + .data = data +MVNETA_SKB_HEADROOM , + .rxq = &rxq->xdp_rxq, + }; +xdp_set_data_meta_invalid (&xdp);if (MVNETA_SKB_SIZE (rx_desc->data_size) >PAGE_SIZE ) { len =MVNETA_MAX_RX_BUF_SIZE ;@@ -1943,13 +1992,24 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp, len = rx_desc->data_size; data_len += (len -ETH_FCS_LEN ); } + xdp.data_end = xdp.data + data_len; dma_dir =page_pool_get_dma_dir (rxq->page_pool);drivers/net/ethernet/marvell/mvneta.c mvneta_swbm_rx_frame(struct mvneta_port *pp, · line 2006
Quoted 10 lines
drivers/net/ethernet/marvell/mvneta.c +5
-1dma_sync_single_range_for_cpu (dev->dev.parent, rx_desc->buf_phys_addr,0 , len, dma_dir); - rxq->skb =build_skb (data,PAGE_SIZE ); +if (xdp_prog) { +int ret; + + ret =mvneta_run_xdp (pp, xdp_prog, &xdp); +if (ret !=MVNETA_XDP_PASS ) {Nit: you could have it written as:
if (mvneta_run_xdp(...)) { //blah }since
MVNETA_XDP_PASSis 0. The 'ret' variable is not needed here.Quoted 99 lines
drivers/net/ethernet/marvell/mvneta.c +21
-6+ rx_desc->buf_phys_addr =0 ; +return -EAGAIN ; + } + } + + rxq->skb =build_skb (xdp.data_hard_start,PAGE_SIZE );if (unlikely (!rxq->skb)) { netdev_err(dev, "Can't allocate skb on queue %d\n",@@ -1959,8 +2019,9 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp,return -ENOMEM ; } -skb_reserve (rxq->skb,MVNETA_MH_SIZE +NET_SKB_PAD ); -skb_put (rxq->skb, data_len); +skb_reserve (rxq->skb, +MVNETA_MH_SIZE + xdp.data - xdp.data_hard_start); +skb_put (rxq->skb, xdp.data_end - xdp.data);mvneta_rx_csum (pp, rx_desc->status, rxq->skb);page_pool_release_page (rxq->page_pool, page);@@ -1995,7 +2056,7 @@ mvneta_swbm_add_rx_fragment(struct mvneta_port *pp,/* refill descriptor with new buffer later */ skb_add_rx_frag (rxq->skb,skb_shinfo (rxq->skb)->nr_frags, - page,NET_SKB_PAD , data_len, + page,MVNETA_SKB_HEADROOM , data_len,PAGE_SIZE );page_pool_release_page (rxq->page_pool, page);@@ -2011,10 +2072,14 @@ static int mvneta_rx_swbm(struct napi_struct *napi, {int rcvd_pkts =0 , rcvd_bytes =0 ;int rx_todo, rx_proc =0 , refill; +struct bpf_prog *xdp_prog;/* Get number of received packets */ rx_todo =mvneta_rxq_busy_desc_num_get (pp, rxq); +rcu_read_lock (); + xdp_prog =READ_ONCE (pp->xdp_prog); +/* Fairness NAPI loop */ while (rcvd_pkts < budget && rx_proc < rx_todo) {struct mvneta_rx_desc *rx_desc =mvneta_rxq_next_desc_get (rxq);@@ -2029,6 +2094,7 @@ static int mvneta_rx_swbm(struct napi_struct *napi,prefetch (data); rxq->refill_num++; + rcvd_pkts++; rx_proc++;if (rx_desc->status &MVNETA_RXD_FIRST_DESC ) {@@ -2042,7 +2108,8 @@ static int mvneta_rx_swbm(struct napi_struct *napi,continue ; } - err =mvneta_swbm_rx_frame (pp, rx_desc, rxq, page); + err =mvneta_swbm_rx_frame (pp, rx_desc, rxq, + xdp_prog, page);if (err <0 )continue ; }else {@@ -2066,7 +2133,6 @@ static int mvneta_rx_swbm(struct napi_struct *napi, rxq->skb =NULL ;continue ; } - rcvd_pkts++; rcvd_bytes += rxq->skb->len;/* Linux processing */ @@ -2077,6 +2143,7 @@ static int mvneta_rx_swbm(struct napi_struct *napi,/* clean uncomplete skb pointer in queue */ rxq->skb =NULL ; } +rcu_read_unlock ();if (rcvd_pkts) {struct mvneta_pcpu_stats *stats =this_cpu_ptr (pp->stats);@@ -2836,14 +2903,16 @@ static int mvneta_poll(struct napi_struct *napi, int budget)static int mvneta_create_page_pool (struct mvneta_port *pp,struct mvneta_rx_queue *rxq,int size) { +struct bpf_prog *xdp_prog =READ_ONCE (pp->xdp_prog);struct page_pool_params pp_params = { .order =0 , .flags =PP_FLAG_DMA_MAP , .pool_size = size, .nid =cpu_to_node (0 ), .dev = pp->dev->dev.parent, - .dma_dir =DMA_FROM_DEVICE , + .dma_dir = xdp_prog ?DMA_BIDIRECTIONAL :DMA_FROM_DEVICE , }; +int err; rxq->page_pool =page_pool_create (&pp_params);if (IS_ERR (rxq->page_pool)) {@@ -2851,7 +2920,22 @@ static int mvneta_create_page_pool(struct mvneta_port *pp,return PTR_ERR (rxq->page_pool);drivers/net/ethernet/marvell/mvneta.c static int mvneta_create_page_pool(struct mvneta_port *pp, · line 2930
Quoted 10 lines
drivers/net/ethernet/marvell/mvneta.c +8
-0} + err =xdp_rxq_info_reg (&rxq->xdp_rxq, pp->dev,0 ); +if (err <0 ) + goto err_free_pp; + + err =xdp_rxq_info_reg_mem_model (&rxq->xdp_rxq,MEM_TYPE_PAGE_POOL , + rxq->page_pool); +if (err) + goto err_unregister_pp;
err_unregister_rxq?Quoted 50 lines
drivers/net/ethernet/marvell/mvneta.c +35
-0+return 0 ; + +err_unregister_pp: +xdp_rxq_info_unreg (&rxq->xdp_rxq); +err_free_pp: +page_pool_destroy (rxq->page_pool); +return err; }/* Handle rxq fill: allocates rxq skbs; called when initializing a port */ @@ -3291,6 +3375,11 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) mtu =ALIGN (MVNETA_RX_PKT_SIZE (mtu),8 ); } +if (pp->xdp_prog && mtu >MVNETA_MAX_RX_BUF_SIZE ) { +netdev_info (dev,"Illegal MTU value %d for XDP mode\n" , mtu); +return -EINVAL ; + } + dev->mtu = mtu;if (!netif_running (dev)) {@@ -3960,6 +4049,43 @@ static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)return phylink_mii_ioctl (pp->phylink, ifr, cmd); } +static int mvneta_xdp_setup (struct net_device *dev,struct bpf_prog *prog, +struct netlink_ext_ack *extack) +{ +struct mvneta_port *pp =netdev_priv (dev); +struct bpf_prog *old_prog; + +if (prog && dev->mtu >MVNETA_MAX_RX_BUF_SIZE ) { +NL_SET_ERR_MSG_MOD (extack,"Jumbo frames not supported on XDP" ); +return -EOPNOTSUPP ; + } + +mvneta_stop (dev); + + old_prog =xchg (&pp->xdp_prog, prog); +if (old_prog) +bpf_prog_put (old_prog); + +mvneta_open (dev); + +return 0 ; +} + +static int mvneta_xdp (struct net_device *dev,struct netdev_bpf *xdp)drivers/net/ethernet/marvell/mvneta.c static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) · line 4084
Quoted 10 lines
drivers/net/ethernet/marvell/mvneta.c +10
-0+{ +struct mvneta_port *pp =netdev_priv (dev); + +switch (xdp->command) { +case XDP_SETUP_PROG : +return mvneta_xdp_setup (dev, xdp->prog, xdp->extack); +case XDP_QUERY_PROG : + xdp->prog_id = pp->xdp_prog ? pp->xdp_prog->aux->id :0 ; +return 0 ; +default :
NL_SET_ERR_MSG_MOD(xdp->extack, "Unknown XDP command"); ?Quoted 24 lines
drivers/net/ethernet/marvell/mvneta.c +6
-1+return -EINVAL ; + } +} +/* Ethtool methods */ /* Set link ksettings (phy address, speed) for ethtools */ @@ -4356,6 +4482,7 @@ static const struct net_device_ops mvneta_netdev_ops = { .ndo_fix_features = mvneta_fix_features, .ndo_get_stats64 = mvneta_get_stats64, .ndo_do_ioctl = mvneta_ioctl, + .ndo_bpf = mvneta_xdp, };static const struct ethtool_ops mvneta_eth_tool_ops = {@@ -4646,7 +4773,7 @@ static int mvneta_probe(struct platform_device *pdev)SET_NETDEV_DEV (dev, &pdev->dev); pp->id = global_port_id++; - pp->rx_offset_correction =NET_SKB_PAD ; + pp->rx_offset_correction =MVNETA_SKB_HEADROOM ;/* Obtain access to BM resources if enabled and already initialized */ bm_node =of_parse_phandle (dn,"buffer-manager" ,0 );
Re: [RFC 3/4] net: mvneta: add basic XDP support
In reply to Lorenzo BianconiQuoted 15 lines · Lorenzo Bianconi
Add basic XDP support to mvneta driver for devices that rely on software buffer management. Currently supported verdicts are:
-XDP_DROP
-XDP_PASS
-XDP_REDIRECTSigned-off-by Lorenzo Bianconi <[email protected]>--- drivers/net/ethernet/marvell/mvneta.c | 145 ++++++++++++++++++++++++-- 1 file changed, 136 insertions(+), 9 deletions(-)drivers/net/ethernet/marvell/mvneta.c +0
-0
[...]
Quoted 12 lines
drivers/net/ethernet/marvell/mvneta.c +2
-1.pool_size = size, .nid = cpu_to_node(0), .dev = pp->dev->dev.parent, - .dma_dir = DMA_FROM_DEVICE, + .dma_dir = xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE, }; +int err; rxq->page_pool =page_pool_create (&pp_params);if (IS_ERR (rxq->page_pool)) {@@ -2851,7 +2920,22 @@ static int mvneta_create_page_pool(struct mvneta_port *pp,return PTR_ERR (rxq->page_pool);
drivers/net/ethernet/marvell/mvneta.c static int mvneta_create_page_pool(struct mvneta_port *pp, · line 2930
Quoted 10 lines
drivers/net/ethernet/marvell/mvneta.c +8
-0} + err =xdp_rxq_info_reg (&rxq->xdp_rxq, pp->dev,0 ); +if (err <0 ) + goto err_free_pp; + + err =xdp_rxq_info_reg_mem_model (&rxq->xdp_rxq,MEM_TYPE_PAGE_POOL , + rxq->page_pool); +if (err) + goto err_unregister_pp;
I think this should be part of patch [1/4], adding page pol support. Jesper introduced the changes to track down inflight packets [1], so you need those changes in place when implementing page_pool
Quoted 87 lines
drivers/net/ethernet/marvell/mvneta.c +51
-1+return 0 ; + +err_unregister_pp: +xdp_rxq_info_unreg (&rxq->xdp_rxq); +err_free_pp: +page_pool_destroy (rxq->page_pool); +return err; }/* Handle rxq fill: allocates rxq skbs; called when initializing a port */ @@ -3291,6 +3375,11 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) mtu =ALIGN (MVNETA_RX_PKT_SIZE (mtu),8 ); } +if (pp->xdp_prog && mtu >MVNETA_MAX_RX_BUF_SIZE ) { +netdev_info (dev,"Illegal MTU value %d for XDP mode\n" , mtu); +return -EINVAL ; + } + dev->mtu = mtu;if (!netif_running (dev)) {@@ -3960,6 +4049,43 @@ static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)return phylink_mii_ioctl (pp->phylink, ifr, cmd); } +static int mvneta_xdp_setup (struct net_device *dev,struct bpf_prog *prog, +struct netlink_ext_ack *extack) +{ +struct mvneta_port *pp =netdev_priv (dev); +struct bpf_prog *old_prog; + +if (prog && dev->mtu >MVNETA_MAX_RX_BUF_SIZE ) { +NL_SET_ERR_MSG_MOD (extack,"Jumbo frames not supported on XDP" ); +return -EOPNOTSUPP ; + } + +mvneta_stop (dev); + + old_prog =xchg (&pp->xdp_prog, prog); +if (old_prog) +bpf_prog_put (old_prog); + +mvneta_open (dev); + +return 0 ; +} + +static int mvneta_xdp (struct net_device *dev,struct netdev_bpf *xdp) +{ +struct mvneta_port *pp =netdev_priv (dev); + +switch (xdp->command) { +case XDP_SETUP_PROG : +return mvneta_xdp_setup (dev, xdp->prog, xdp->extack); +case XDP_QUERY_PROG : + xdp->prog_id = pp->xdp_prog ? pp->xdp_prog->aux->id :0 ; +return 0 ; +default : +return -EINVAL ; + } +} +/* Ethtool methods */ /* Set link ksettings (phy address, speed) for ethtools */ @@ -4356,6 +4482,7 @@ static const struct net_device_ops mvneta_netdev_ops = { .ndo_fix_features = mvneta_fix_features, .ndo_get_stats64 = mvneta_get_stats64, .ndo_do_ioctl = mvneta_ioctl, + .ndo_bpf = mvneta_xdp, };static const struct ethtool_ops mvneta_eth_tool_ops = {@@ -4646,7 +4773,7 @@ static int mvneta_probe(struct platform_device *pdev)SET_NETDEV_DEV (dev, &pdev->dev); pp->id = global_port_id++; - pp->rx_offset_correction =NET_SKB_PAD ; + pp->rx_offset_correction =MVNETA_SKB_HEADROOM ;/* Obtain access to BM resources if enabled and already initialized */ bm_node =of_parse_phandle (dn,"buffer-manager" ,0 );Signature · 1 line
2.21.0
[1] https://lore.kernel.org/netdev/156086304827.27760.11339786046465638081.stgit@firesoul/
Regards
/Ilias
Re: [RFC 3/4] net: mvneta: add basic XDP support
Quoted 31 lines · Lorenzo Bianconi
Quoted 15 lines
Add basic XDP support to mvneta driver for devices that rely on software buffer management. Currently supported verdicts are:
-XDP_DROP
-XDP_PASS
-XDP_REDIRECTSigned-off-by Lorenzo Bianconi <[email protected]>--- drivers/net/ethernet/marvell/mvneta.c | 145 ++++++++++++++++++++++++-- 1 file changed, 136 insertions(+), 9 deletions(-)drivers/net/ethernet/marvell/mvneta.c +0
-0[...]
Quoted 14 lines
drivers/net/ethernet/marvell/mvneta.c +2
-1.pool_size = size, .nid = cpu_to_node(0), .dev = pp->dev->dev.parent, - .dma_dir = DMA_FROM_DEVICE, + .dma_dir = xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE, }; +int err; rxq->page_pool =page_pool_create (&pp_params);if (IS_ERR (rxq->page_pool)) {@@ -2851,7 +2920,22 @@ static int mvneta_create_page_pool(struct mvneta_port *pp,return PTR_ERR (rxq->page_pool); }
Quoted 12 lines
drivers/net/ethernet/marvell/mvneta.c static int mvneta_create_page_pool(struct mvneta_port *pp, · line 2930
Quoted 8 lines
drivers/net/ethernet/marvell/mvneta.c +8
-0+ err =xdp_rxq_info_reg (&rxq->xdp_rxq, pp->dev,0 ); +if (err <0 ) + goto err_free_pp; + + err =xdp_rxq_info_reg_mem_model (&rxq->xdp_rxq,MEM_TYPE_PAGE_POOL , + rxq->page_pool); +if (err) + goto err_unregister_pp;I think this should be part of patch [1/4], adding page pol support. Jesper introduced the changes to track down inflight packets [1], so you need those changes in place when implementing
page_pool
ack, will do in the next round.
Regards,
Lorenzo
Quoted 94 lines
Quoted 88 lines
drivers/net/ethernet/marvell/mvneta.c +51
-1+return 0 ; + +err_unregister_pp: +xdp_rxq_info_unreg (&rxq->xdp_rxq); +err_free_pp: +page_pool_destroy (rxq->page_pool); +return err; }/* Handle rxq fill: allocates rxq skbs; called when initializing a port */ @@ -3291,6 +3375,11 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) mtu =ALIGN (MVNETA_RX_PKT_SIZE (mtu),8 ); } +if (pp->xdp_prog && mtu >MVNETA_MAX_RX_BUF_SIZE ) { +netdev_info (dev,"Illegal MTU value %d for XDP mode\n" , mtu); +return -EINVAL ; + } + dev->mtu = mtu;if (!netif_running (dev)) {@@ -3960,6 +4049,43 @@ static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)return phylink_mii_ioctl (pp->phylink, ifr, cmd); } +static int mvneta_xdp_setup (struct net_device *dev,struct bpf_prog *prog, +struct netlink_ext_ack *extack) +{ +struct mvneta_port *pp =netdev_priv (dev); +struct bpf_prog *old_prog; + +if (prog && dev->mtu >MVNETA_MAX_RX_BUF_SIZE ) { +NL_SET_ERR_MSG_MOD (extack,"Jumbo frames not supported on XDP" ); +return -EOPNOTSUPP ; + } + +mvneta_stop (dev); + + old_prog =xchg (&pp->xdp_prog, prog); +if (old_prog) +bpf_prog_put (old_prog); + +mvneta_open (dev); + +return 0 ; +} + +static int mvneta_xdp (struct net_device *dev,struct netdev_bpf *xdp) +{ +struct mvneta_port *pp =netdev_priv (dev); + +switch (xdp->command) { +case XDP_SETUP_PROG : +return mvneta_xdp_setup (dev, xdp->prog, xdp->extack); +case XDP_QUERY_PROG : + xdp->prog_id = pp->xdp_prog ? pp->xdp_prog->aux->id :0 ; +return 0 ; +default : +return -EINVAL ; + } +} +/* Ethtool methods */ /* Set link ksettings (phy address, speed) for ethtools */ @@ -4356,6 +4482,7 @@ static const struct net_device_ops mvneta_netdev_ops = { .ndo_fix_features = mvneta_fix_features, .ndo_get_stats64 = mvneta_get_stats64, .ndo_do_ioctl = mvneta_ioctl, + .ndo_bpf = mvneta_xdp, };static const struct ethtool_ops mvneta_eth_tool_ops = {@@ -4646,7 +4773,7 @@ static int mvneta_probe(struct platform_device *pdev)SET_NETDEV_DEV (dev, &pdev->dev); pp->id = global_port_id++; - pp->rx_offset_correction =NET_SKB_PAD ; + pp->rx_offset_correction =MVNETA_SKB_HEADROOM ;/* Obtain access to BM resources if enabled and already initialized */ bm_node =of_parse_phandle (dn,"buffer-manager" ,0 );Signature · 1 line
2.21.0[1] https://lore.kernel.org/netdev/156086304827.27760.11339786046465638081.stgit@firesoul/
Regards
/Ilias
RFC 4/4 net: mvneta: move header prefetch in mvneta_swbm_rx_frame
In reply to Lorenzo BianconiMove data buffer prefetch in mvneta_swbm_rx_frame after dma_sync_single_range_for_cpu
--- drivers/net/ethernet/marvell/mvneta.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
drivers/net/ethernet/marvell/mvneta.c +8 -8
@@ -1979,11 +1979,8 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp,struct net_device *dev = pp->dev;enum dma_data_direction dma_dir;struct xdp_buff xdp = { - .data_hard_start = data, - .data = data +MVNETA_SKB_HEADROOM , .rxq = &rxq->xdp_rxq, }; -xdp_set_data_meta_invalid (&xdp);if (MVNETA_SKB_SIZE (rx_desc->data_size) >PAGE_SIZE ) { len =MVNETA_MAX_RX_BUF_SIZE ;
@@ -1992,13 +1989,20 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp, len = rx_desc->data_size; data_len += (len -ETH_FCS_LEN ); } - xdp.data_end = xdp.data + data_len; dma_dir =page_pool_get_dma_dir (rxq->page_pool);dma_sync_single_range_for_cpu (dev->dev.parent, rx_desc->buf_phys_addr,0 , len, dma_dir); +/* Prefetch header */ +prefetch (data); + + xdp.data_hard_start = data; + xdp.data = data +MVNETA_SKB_HEADROOM ; + xdp.data_end = xdp.data + data_len; +xdp_set_data_meta_invalid (&xdp); +if (xdp_prog) {int ret;
@@ -2083,15 +2087,11 @@ static int mvneta_rx_swbm(struct napi_struct *napi,/* Fairness NAPI loop */ while (rcvd_pkts < budget && rx_proc < rx_todo) {struct mvneta_rx_desc *rx_desc =mvneta_rxq_next_desc_get (rxq); -unsigned char *data;struct page *page;int index; index = rx_desc - rxq->descs; page = (struct page *)rxq->buf_virt_addr[index]; - data =page_address (page); -/* Prefetch header */ -prefetch (data); rxq->refill_num++; rcvd_pkts++;
Signature · 1 line
2.21.0