18c2ecf20Sopenharmony_ci/* Broadcom NetXtreme-C/E network driver. 28c2ecf20Sopenharmony_ci * 38c2ecf20Sopenharmony_ci * Copyright (c) 2016-2017 Broadcom Limited 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 68c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by 78c2ecf20Sopenharmony_ci * the Free Software Foundation. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/errno.h> 118c2ecf20Sopenharmony_ci#include <linux/pci.h> 128c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 138c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 148c2ecf20Sopenharmony_ci#include <linux/if_vlan.h> 158c2ecf20Sopenharmony_ci#include <linux/bpf.h> 168c2ecf20Sopenharmony_ci#include <linux/bpf_trace.h> 178c2ecf20Sopenharmony_ci#include <linux/filter.h> 188c2ecf20Sopenharmony_ci#include <net/page_pool.h> 198c2ecf20Sopenharmony_ci#include "bnxt_hsi.h" 208c2ecf20Sopenharmony_ci#include "bnxt.h" 218c2ecf20Sopenharmony_ci#include "bnxt_xdp.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistruct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp, 248c2ecf20Sopenharmony_ci struct bnxt_tx_ring_info *txr, 258c2ecf20Sopenharmony_ci dma_addr_t mapping, u32 len) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci struct bnxt_sw_tx_bd *tx_buf; 288c2ecf20Sopenharmony_ci struct tx_bd *txbd; 298c2ecf20Sopenharmony_ci u32 flags; 308c2ecf20Sopenharmony_ci u16 prod; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci prod = txr->tx_prod; 338c2ecf20Sopenharmony_ci tx_buf = &txr->tx_buf_ring[prod]; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)]; 368c2ecf20Sopenharmony_ci flags = (len << TX_BD_LEN_SHIFT) | (1 << TX_BD_FLAGS_BD_CNT_SHIFT) | 378c2ecf20Sopenharmony_ci TX_BD_FLAGS_PACKET_END | bnxt_lhint_arr[len >> 9]; 388c2ecf20Sopenharmony_ci txbd->tx_bd_len_flags_type = cpu_to_le32(flags); 398c2ecf20Sopenharmony_ci txbd->tx_bd_opaque = prod; 408c2ecf20Sopenharmony_ci txbd->tx_bd_haddr = cpu_to_le64(mapping); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci prod = NEXT_TX(prod); 438c2ecf20Sopenharmony_ci txr->tx_prod = prod; 448c2ecf20Sopenharmony_ci return tx_buf; 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic void __bnxt_xmit_xdp(struct bnxt *bp, struct bnxt_tx_ring_info *txr, 488c2ecf20Sopenharmony_ci dma_addr_t mapping, u32 len, u16 rx_prod) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci struct bnxt_sw_tx_bd *tx_buf; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci tx_buf = bnxt_xmit_bd(bp, txr, mapping, len); 538c2ecf20Sopenharmony_ci tx_buf->rx_prod = rx_prod; 548c2ecf20Sopenharmony_ci tx_buf->action = XDP_TX; 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic void __bnxt_xmit_xdp_redirect(struct bnxt *bp, 588c2ecf20Sopenharmony_ci struct bnxt_tx_ring_info *txr, 598c2ecf20Sopenharmony_ci dma_addr_t mapping, u32 len, 608c2ecf20Sopenharmony_ci struct xdp_frame *xdpf) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci struct bnxt_sw_tx_bd *tx_buf; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci tx_buf = bnxt_xmit_bd(bp, txr, mapping, len); 658c2ecf20Sopenharmony_ci tx_buf->action = XDP_REDIRECT; 668c2ecf20Sopenharmony_ci tx_buf->xdpf = xdpf; 678c2ecf20Sopenharmony_ci dma_unmap_addr_set(tx_buf, mapping, mapping); 688c2ecf20Sopenharmony_ci dma_unmap_len_set(tx_buf, len, 0); 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_civoid bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci struct bnxt_tx_ring_info *txr = bnapi->tx_ring; 748c2ecf20Sopenharmony_ci struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; 758c2ecf20Sopenharmony_ci bool rx_doorbell_needed = false; 768c2ecf20Sopenharmony_ci struct bnxt_sw_tx_bd *tx_buf; 778c2ecf20Sopenharmony_ci u16 tx_cons = txr->tx_cons; 788c2ecf20Sopenharmony_ci u16 last_tx_cons = tx_cons; 798c2ecf20Sopenharmony_ci int i; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci for (i = 0; i < nr_pkts; i++) { 828c2ecf20Sopenharmony_ci tx_buf = &txr->tx_buf_ring[tx_cons]; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if (tx_buf->action == XDP_REDIRECT) { 858c2ecf20Sopenharmony_ci struct pci_dev *pdev = bp->pdev; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci dma_unmap_single(&pdev->dev, 888c2ecf20Sopenharmony_ci dma_unmap_addr(tx_buf, mapping), 898c2ecf20Sopenharmony_ci dma_unmap_len(tx_buf, len), 908c2ecf20Sopenharmony_ci PCI_DMA_TODEVICE); 918c2ecf20Sopenharmony_ci xdp_return_frame(tx_buf->xdpf); 928c2ecf20Sopenharmony_ci tx_buf->action = 0; 938c2ecf20Sopenharmony_ci tx_buf->xdpf = NULL; 948c2ecf20Sopenharmony_ci } else if (tx_buf->action == XDP_TX) { 958c2ecf20Sopenharmony_ci rx_doorbell_needed = true; 968c2ecf20Sopenharmony_ci last_tx_cons = tx_cons; 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci tx_cons = NEXT_TX(tx_cons); 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci txr->tx_cons = tx_cons; 1018c2ecf20Sopenharmony_ci if (rx_doorbell_needed) { 1028c2ecf20Sopenharmony_ci tx_buf = &txr->tx_buf_ring[last_tx_cons]; 1038c2ecf20Sopenharmony_ci bnxt_db_write(bp, &rxr->rx_db, tx_buf->rx_prod); 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/* returns the following: 1088c2ecf20Sopenharmony_ci * true - packet consumed by XDP and new buffer is allocated. 1098c2ecf20Sopenharmony_ci * false - packet should be passed to the stack. 1108c2ecf20Sopenharmony_ci */ 1118c2ecf20Sopenharmony_cibool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, 1128c2ecf20Sopenharmony_ci struct page *page, u8 **data_ptr, unsigned int *len, u8 *event) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci struct bpf_prog *xdp_prog = READ_ONCE(rxr->xdp_prog); 1158c2ecf20Sopenharmony_ci struct bnxt_tx_ring_info *txr; 1168c2ecf20Sopenharmony_ci struct bnxt_sw_rx_bd *rx_buf; 1178c2ecf20Sopenharmony_ci struct pci_dev *pdev; 1188c2ecf20Sopenharmony_ci struct xdp_buff xdp; 1198c2ecf20Sopenharmony_ci dma_addr_t mapping; 1208c2ecf20Sopenharmony_ci void *orig_data; 1218c2ecf20Sopenharmony_ci u32 tx_avail; 1228c2ecf20Sopenharmony_ci u32 offset; 1238c2ecf20Sopenharmony_ci u32 act; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci if (!xdp_prog) 1268c2ecf20Sopenharmony_ci return false; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci pdev = bp->pdev; 1298c2ecf20Sopenharmony_ci rx_buf = &rxr->rx_buf_ring[cons]; 1308c2ecf20Sopenharmony_ci offset = bp->rx_offset; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci mapping = rx_buf->mapping - bp->rx_dma_offset; 1338c2ecf20Sopenharmony_ci dma_sync_single_for_cpu(&pdev->dev, mapping + offset, *len, bp->rx_dir); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci txr = rxr->bnapi->tx_ring; 1368c2ecf20Sopenharmony_ci xdp.data_hard_start = *data_ptr - offset; 1378c2ecf20Sopenharmony_ci xdp.data = *data_ptr; 1388c2ecf20Sopenharmony_ci xdp_set_data_meta_invalid(&xdp); 1398c2ecf20Sopenharmony_ci xdp.data_end = *data_ptr + *len; 1408c2ecf20Sopenharmony_ci xdp.rxq = &rxr->xdp_rxq; 1418c2ecf20Sopenharmony_ci xdp.frame_sz = PAGE_SIZE; /* BNXT_RX_PAGE_MODE(bp) when XDP enabled */ 1428c2ecf20Sopenharmony_ci orig_data = xdp.data; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci rcu_read_lock(); 1458c2ecf20Sopenharmony_ci act = bpf_prog_run_xdp(xdp_prog, &xdp); 1468c2ecf20Sopenharmony_ci rcu_read_unlock(); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci tx_avail = bnxt_tx_avail(bp, txr); 1498c2ecf20Sopenharmony_ci /* If the tx ring is not full, we must not update the rx producer yet 1508c2ecf20Sopenharmony_ci * because we may still be transmitting on some BDs. 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_ci if (tx_avail != bp->tx_ring_size) 1538c2ecf20Sopenharmony_ci *event &= ~BNXT_RX_EVENT; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci *len = xdp.data_end - xdp.data; 1568c2ecf20Sopenharmony_ci if (orig_data != xdp.data) { 1578c2ecf20Sopenharmony_ci offset = xdp.data - xdp.data_hard_start; 1588c2ecf20Sopenharmony_ci *data_ptr = xdp.data_hard_start + offset; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci switch (act) { 1618c2ecf20Sopenharmony_ci case XDP_PASS: 1628c2ecf20Sopenharmony_ci return false; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci case XDP_TX: 1658c2ecf20Sopenharmony_ci if (tx_avail < 1) { 1668c2ecf20Sopenharmony_ci trace_xdp_exception(bp->dev, xdp_prog, act); 1678c2ecf20Sopenharmony_ci bnxt_reuse_rx_data(rxr, cons, page); 1688c2ecf20Sopenharmony_ci return true; 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci *event = BNXT_TX_EVENT; 1728c2ecf20Sopenharmony_ci dma_sync_single_for_device(&pdev->dev, mapping + offset, *len, 1738c2ecf20Sopenharmony_ci bp->rx_dir); 1748c2ecf20Sopenharmony_ci __bnxt_xmit_xdp(bp, txr, mapping + offset, *len, 1758c2ecf20Sopenharmony_ci NEXT_RX(rxr->rx_prod)); 1768c2ecf20Sopenharmony_ci bnxt_reuse_rx_data(rxr, cons, page); 1778c2ecf20Sopenharmony_ci return true; 1788c2ecf20Sopenharmony_ci case XDP_REDIRECT: 1798c2ecf20Sopenharmony_ci /* if we are calling this here then we know that the 1808c2ecf20Sopenharmony_ci * redirect is coming from a frame received by the 1818c2ecf20Sopenharmony_ci * bnxt_en driver. 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_ci dma_unmap_page_attrs(&pdev->dev, mapping, 1848c2ecf20Sopenharmony_ci PAGE_SIZE, bp->rx_dir, 1858c2ecf20Sopenharmony_ci DMA_ATTR_WEAK_ORDERING); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci /* if we are unable to allocate a new buffer, abort and reuse */ 1888c2ecf20Sopenharmony_ci if (bnxt_alloc_rx_data(bp, rxr, rxr->rx_prod, GFP_ATOMIC)) { 1898c2ecf20Sopenharmony_ci trace_xdp_exception(bp->dev, xdp_prog, act); 1908c2ecf20Sopenharmony_ci bnxt_reuse_rx_data(rxr, cons, page); 1918c2ecf20Sopenharmony_ci return true; 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if (xdp_do_redirect(bp->dev, &xdp, xdp_prog)) { 1958c2ecf20Sopenharmony_ci trace_xdp_exception(bp->dev, xdp_prog, act); 1968c2ecf20Sopenharmony_ci page_pool_recycle_direct(rxr->page_pool, page); 1978c2ecf20Sopenharmony_ci return true; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci *event |= BNXT_REDIRECT_EVENT; 2018c2ecf20Sopenharmony_ci break; 2028c2ecf20Sopenharmony_ci default: 2038c2ecf20Sopenharmony_ci bpf_warn_invalid_xdp_action(act); 2048c2ecf20Sopenharmony_ci fallthrough; 2058c2ecf20Sopenharmony_ci case XDP_ABORTED: 2068c2ecf20Sopenharmony_ci trace_xdp_exception(bp->dev, xdp_prog, act); 2078c2ecf20Sopenharmony_ci fallthrough; 2088c2ecf20Sopenharmony_ci case XDP_DROP: 2098c2ecf20Sopenharmony_ci bnxt_reuse_rx_data(rxr, cons, page); 2108c2ecf20Sopenharmony_ci break; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci return true; 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ciint bnxt_xdp_xmit(struct net_device *dev, int num_frames, 2168c2ecf20Sopenharmony_ci struct xdp_frame **frames, u32 flags) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci struct bnxt *bp = netdev_priv(dev); 2198c2ecf20Sopenharmony_ci struct bpf_prog *xdp_prog = READ_ONCE(bp->xdp_prog); 2208c2ecf20Sopenharmony_ci struct pci_dev *pdev = bp->pdev; 2218c2ecf20Sopenharmony_ci struct bnxt_tx_ring_info *txr; 2228c2ecf20Sopenharmony_ci dma_addr_t mapping; 2238c2ecf20Sopenharmony_ci int drops = 0; 2248c2ecf20Sopenharmony_ci int ring; 2258c2ecf20Sopenharmony_ci int i; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (!test_bit(BNXT_STATE_OPEN, &bp->state) || 2288c2ecf20Sopenharmony_ci !bp->tx_nr_rings_xdp || 2298c2ecf20Sopenharmony_ci !xdp_prog) 2308c2ecf20Sopenharmony_ci return -EINVAL; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci ring = smp_processor_id() % bp->tx_nr_rings_xdp; 2338c2ecf20Sopenharmony_ci txr = &bp->tx_ring[ring]; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci for (i = 0; i < num_frames; i++) { 2368c2ecf20Sopenharmony_ci struct xdp_frame *xdp = frames[i]; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci if (!txr || !bnxt_tx_avail(bp, txr) || 2398c2ecf20Sopenharmony_ci !(bp->bnapi[ring]->flags & BNXT_NAPI_FLAG_XDP)) { 2408c2ecf20Sopenharmony_ci xdp_return_frame_rx_napi(xdp); 2418c2ecf20Sopenharmony_ci drops++; 2428c2ecf20Sopenharmony_ci continue; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci mapping = dma_map_single(&pdev->dev, xdp->data, xdp->len, 2468c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci if (dma_mapping_error(&pdev->dev, mapping)) { 2498c2ecf20Sopenharmony_ci xdp_return_frame_rx_napi(xdp); 2508c2ecf20Sopenharmony_ci drops++; 2518c2ecf20Sopenharmony_ci continue; 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci __bnxt_xmit_xdp_redirect(bp, txr, mapping, xdp->len, xdp); 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci if (flags & XDP_XMIT_FLUSH) { 2578c2ecf20Sopenharmony_ci /* Sync BD data before updating doorbell */ 2588c2ecf20Sopenharmony_ci wmb(); 2598c2ecf20Sopenharmony_ci bnxt_db_write(bp, &txr->tx_db, txr->tx_prod); 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci return num_frames - drops; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci/* Under rtnl_lock */ 2668c2ecf20Sopenharmony_cistatic int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct net_device *dev = bp->dev; 2698c2ecf20Sopenharmony_ci int tx_xdp = 0, rc, tc; 2708c2ecf20Sopenharmony_ci struct bpf_prog *old; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (prog && bp->dev->mtu > BNXT_MAX_PAGE_MODE_MTU) { 2738c2ecf20Sopenharmony_ci netdev_warn(dev, "MTU %d larger than largest XDP supported MTU %d.\n", 2748c2ecf20Sopenharmony_ci bp->dev->mtu, BNXT_MAX_PAGE_MODE_MTU); 2758c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci if (!(bp->flags & BNXT_FLAG_SHARED_RINGS)) { 2788c2ecf20Sopenharmony_ci netdev_warn(dev, "ethtool rx/tx channels must be combined to support XDP.\n"); 2798c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci if (prog) 2828c2ecf20Sopenharmony_ci tx_xdp = bp->rx_nr_rings; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci tc = netdev_get_num_tc(dev); 2858c2ecf20Sopenharmony_ci if (!tc) 2868c2ecf20Sopenharmony_ci tc = 1; 2878c2ecf20Sopenharmony_ci rc = bnxt_check_rings(bp, bp->tx_nr_rings_per_tc, bp->rx_nr_rings, 2888c2ecf20Sopenharmony_ci true, tc, tx_xdp); 2898c2ecf20Sopenharmony_ci if (rc) { 2908c2ecf20Sopenharmony_ci netdev_warn(dev, "Unable to reserve enough TX rings to support XDP.\n"); 2918c2ecf20Sopenharmony_ci return rc; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci if (netif_running(dev)) 2948c2ecf20Sopenharmony_ci bnxt_close_nic(bp, true, false); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci old = xchg(&bp->xdp_prog, prog); 2978c2ecf20Sopenharmony_ci if (old) 2988c2ecf20Sopenharmony_ci bpf_prog_put(old); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci if (prog) { 3018c2ecf20Sopenharmony_ci bnxt_set_rx_skb_mode(bp, true); 3028c2ecf20Sopenharmony_ci } else { 3038c2ecf20Sopenharmony_ci int rx, tx; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci bnxt_set_rx_skb_mode(bp, false); 3068c2ecf20Sopenharmony_ci bnxt_get_max_rings(bp, &rx, &tx, true); 3078c2ecf20Sopenharmony_ci if (rx > 1) { 3088c2ecf20Sopenharmony_ci bp->flags &= ~BNXT_FLAG_NO_AGG_RINGS; 3098c2ecf20Sopenharmony_ci bp->dev->hw_features |= NETIF_F_LRO; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci bp->tx_nr_rings_xdp = tx_xdp; 3138c2ecf20Sopenharmony_ci bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc + tx_xdp; 3148c2ecf20Sopenharmony_ci bp->cp_nr_rings = max_t(int, bp->tx_nr_rings, bp->rx_nr_rings); 3158c2ecf20Sopenharmony_ci bnxt_set_tpa_flags(bp); 3168c2ecf20Sopenharmony_ci bnxt_set_ring_params(bp); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (netif_running(dev)) 3198c2ecf20Sopenharmony_ci return bnxt_open_nic(bp, true, false); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci return 0; 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ciint bnxt_xdp(struct net_device *dev, struct netdev_bpf *xdp) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci struct bnxt *bp = netdev_priv(dev); 3278c2ecf20Sopenharmony_ci int rc; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci switch (xdp->command) { 3308c2ecf20Sopenharmony_ci case XDP_SETUP_PROG: 3318c2ecf20Sopenharmony_ci rc = bnxt_xdp_set(bp, xdp->prog); 3328c2ecf20Sopenharmony_ci break; 3338c2ecf20Sopenharmony_ci default: 3348c2ecf20Sopenharmony_ci rc = -EINVAL; 3358c2ecf20Sopenharmony_ci break; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci return rc; 3388c2ecf20Sopenharmony_ci} 339