18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include "ixgbe.h" 58c2ecf20Sopenharmony_ci#include "ixgbe_sriov.h" 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifdef CONFIG_IXGBE_DCB 88c2ecf20Sopenharmony_ci/** 98c2ecf20Sopenharmony_ci * ixgbe_cache_ring_dcb_sriov - Descriptor ring to register mapping for SR-IOV 108c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Cache the descriptor ring offsets for SR-IOV to the assigned rings. It 138c2ecf20Sopenharmony_ci * will also try to cache the proper offsets if RSS/FCoE are enabled along 148c2ecf20Sopenharmony_ci * with VMDq. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci **/ 178c2ecf20Sopenharmony_cistatic bool ixgbe_cache_ring_dcb_sriov(struct ixgbe_adapter *adapter) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 208c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *fcoe = &adapter->ring_feature[RING_F_FCOE]; 218c2ecf20Sopenharmony_ci#endif /* IXGBE_FCOE */ 228c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; 238c2ecf20Sopenharmony_ci int i; 248c2ecf20Sopenharmony_ci u16 reg_idx, pool; 258c2ecf20Sopenharmony_ci u8 tcs = adapter->hw_tcs; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci /* verify we have DCB queueing enabled before proceeding */ 288c2ecf20Sopenharmony_ci if (tcs <= 1) 298c2ecf20Sopenharmony_ci return false; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci /* verify we have VMDq enabled before proceeding */ 328c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) 338c2ecf20Sopenharmony_ci return false; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci /* start at VMDq register offset for SR-IOV enabled setups */ 368c2ecf20Sopenharmony_ci reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask); 378c2ecf20Sopenharmony_ci for (i = 0, pool = 0; i < adapter->num_rx_queues; i++, reg_idx++) { 388c2ecf20Sopenharmony_ci /* If we are greater than indices move to next pool */ 398c2ecf20Sopenharmony_ci if ((reg_idx & ~vmdq->mask) >= tcs) { 408c2ecf20Sopenharmony_ci pool++; 418c2ecf20Sopenharmony_ci reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask); 428c2ecf20Sopenharmony_ci } 438c2ecf20Sopenharmony_ci adapter->rx_ring[i]->reg_idx = reg_idx; 448c2ecf20Sopenharmony_ci adapter->rx_ring[i]->netdev = pool ? NULL : adapter->netdev; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask); 488c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++, reg_idx++) { 498c2ecf20Sopenharmony_ci /* If we are greater than indices move to next pool */ 508c2ecf20Sopenharmony_ci if ((reg_idx & ~vmdq->mask) >= tcs) 518c2ecf20Sopenharmony_ci reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask); 528c2ecf20Sopenharmony_ci adapter->tx_ring[i]->reg_idx = reg_idx; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 568c2ecf20Sopenharmony_ci /* nothing to do if FCoE is disabled */ 578c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) 588c2ecf20Sopenharmony_ci return true; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* The work is already done if the FCoE ring is shared */ 618c2ecf20Sopenharmony_ci if (fcoe->offset < tcs) 628c2ecf20Sopenharmony_ci return true; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci /* The FCoE rings exist separately, we need to move their reg_idx */ 658c2ecf20Sopenharmony_ci if (fcoe->indices) { 668c2ecf20Sopenharmony_ci u16 queues_per_pool = __ALIGN_MASK(1, ~vmdq->mask); 678c2ecf20Sopenharmony_ci u8 fcoe_tc = ixgbe_fcoe_get_tc(adapter); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci reg_idx = (vmdq->offset + vmdq->indices) * queues_per_pool; 708c2ecf20Sopenharmony_ci for (i = fcoe->offset; i < adapter->num_rx_queues; i++) { 718c2ecf20Sopenharmony_ci reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask) + fcoe_tc; 728c2ecf20Sopenharmony_ci adapter->rx_ring[i]->reg_idx = reg_idx; 738c2ecf20Sopenharmony_ci adapter->rx_ring[i]->netdev = adapter->netdev; 748c2ecf20Sopenharmony_ci reg_idx++; 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci reg_idx = (vmdq->offset + vmdq->indices) * queues_per_pool; 788c2ecf20Sopenharmony_ci for (i = fcoe->offset; i < adapter->num_tx_queues; i++) { 798c2ecf20Sopenharmony_ci reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask) + fcoe_tc; 808c2ecf20Sopenharmony_ci adapter->tx_ring[i]->reg_idx = reg_idx; 818c2ecf20Sopenharmony_ci reg_idx++; 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#endif /* IXGBE_FCOE */ 868c2ecf20Sopenharmony_ci return true; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci/* ixgbe_get_first_reg_idx - Return first register index associated with ring */ 908c2ecf20Sopenharmony_cistatic void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc, 918c2ecf20Sopenharmony_ci unsigned int *tx, unsigned int *rx) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 948c2ecf20Sopenharmony_ci u8 num_tcs = adapter->hw_tcs; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci *tx = 0; 978c2ecf20Sopenharmony_ci *rx = 0; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci switch (hw->mac.type) { 1008c2ecf20Sopenharmony_ci case ixgbe_mac_82598EB: 1018c2ecf20Sopenharmony_ci /* TxQs/TC: 4 RxQs/TC: 8 */ 1028c2ecf20Sopenharmony_ci *tx = tc << 2; /* 0, 4, 8, 12, 16, 20, 24, 28 */ 1038c2ecf20Sopenharmony_ci *rx = tc << 3; /* 0, 8, 16, 24, 32, 40, 48, 56 */ 1048c2ecf20Sopenharmony_ci break; 1058c2ecf20Sopenharmony_ci case ixgbe_mac_82599EB: 1068c2ecf20Sopenharmony_ci case ixgbe_mac_X540: 1078c2ecf20Sopenharmony_ci case ixgbe_mac_X550: 1088c2ecf20Sopenharmony_ci case ixgbe_mac_X550EM_x: 1098c2ecf20Sopenharmony_ci case ixgbe_mac_x550em_a: 1108c2ecf20Sopenharmony_ci if (num_tcs > 4) { 1118c2ecf20Sopenharmony_ci /* 1128c2ecf20Sopenharmony_ci * TCs : TC0/1 TC2/3 TC4-7 1138c2ecf20Sopenharmony_ci * TxQs/TC: 32 16 8 1148c2ecf20Sopenharmony_ci * RxQs/TC: 16 16 16 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_ci *rx = tc << 4; 1178c2ecf20Sopenharmony_ci if (tc < 3) 1188c2ecf20Sopenharmony_ci *tx = tc << 5; /* 0, 32, 64 */ 1198c2ecf20Sopenharmony_ci else if (tc < 5) 1208c2ecf20Sopenharmony_ci *tx = (tc + 2) << 4; /* 80, 96 */ 1218c2ecf20Sopenharmony_ci else 1228c2ecf20Sopenharmony_ci *tx = (tc + 8) << 3; /* 104, 112, 120 */ 1238c2ecf20Sopenharmony_ci } else { 1248c2ecf20Sopenharmony_ci /* 1258c2ecf20Sopenharmony_ci * TCs : TC0 TC1 TC2/3 1268c2ecf20Sopenharmony_ci * TxQs/TC: 64 32 16 1278c2ecf20Sopenharmony_ci * RxQs/TC: 32 32 32 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci *rx = tc << 5; 1308c2ecf20Sopenharmony_ci if (tc < 2) 1318c2ecf20Sopenharmony_ci *tx = tc << 6; /* 0, 64 */ 1328c2ecf20Sopenharmony_ci else 1338c2ecf20Sopenharmony_ci *tx = (tc + 4) << 4; /* 96, 112 */ 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci default: 1368c2ecf20Sopenharmony_ci break; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci/** 1418c2ecf20Sopenharmony_ci * ixgbe_cache_ring_dcb - Descriptor ring to register mapping for DCB 1428c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 1438c2ecf20Sopenharmony_ci * 1448c2ecf20Sopenharmony_ci * Cache the descriptor ring offsets for DCB to the assigned rings. 1458c2ecf20Sopenharmony_ci * 1468c2ecf20Sopenharmony_ci **/ 1478c2ecf20Sopenharmony_cistatic bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci u8 num_tcs = adapter->hw_tcs; 1508c2ecf20Sopenharmony_ci unsigned int tx_idx, rx_idx; 1518c2ecf20Sopenharmony_ci int tc, offset, rss_i, i; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* verify we have DCB queueing enabled before proceeding */ 1548c2ecf20Sopenharmony_ci if (num_tcs <= 1) 1558c2ecf20Sopenharmony_ci return false; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci rss_i = adapter->ring_feature[RING_F_RSS].indices; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci for (tc = 0, offset = 0; tc < num_tcs; tc++, offset += rss_i) { 1608c2ecf20Sopenharmony_ci ixgbe_get_first_reg_idx(adapter, tc, &tx_idx, &rx_idx); 1618c2ecf20Sopenharmony_ci for (i = 0; i < rss_i; i++, tx_idx++, rx_idx++) { 1628c2ecf20Sopenharmony_ci adapter->tx_ring[offset + i]->reg_idx = tx_idx; 1638c2ecf20Sopenharmony_ci adapter->rx_ring[offset + i]->reg_idx = rx_idx; 1648c2ecf20Sopenharmony_ci adapter->rx_ring[offset + i]->netdev = adapter->netdev; 1658c2ecf20Sopenharmony_ci adapter->tx_ring[offset + i]->dcb_tc = tc; 1668c2ecf20Sopenharmony_ci adapter->rx_ring[offset + i]->dcb_tc = tc; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci return true; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci#endif 1748c2ecf20Sopenharmony_ci/** 1758c2ecf20Sopenharmony_ci * ixgbe_cache_ring_sriov - Descriptor ring to register mapping for sriov 1768c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 1778c2ecf20Sopenharmony_ci * 1788c2ecf20Sopenharmony_ci * SR-IOV doesn't use any descriptor rings but changes the default if 1798c2ecf20Sopenharmony_ci * no other mapping is used. 1808c2ecf20Sopenharmony_ci * 1818c2ecf20Sopenharmony_ci */ 1828c2ecf20Sopenharmony_cistatic bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 1858c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *fcoe = &adapter->ring_feature[RING_F_FCOE]; 1868c2ecf20Sopenharmony_ci#endif /* IXGBE_FCOE */ 1878c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; 1888c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *rss = &adapter->ring_feature[RING_F_RSS]; 1898c2ecf20Sopenharmony_ci u16 reg_idx, pool; 1908c2ecf20Sopenharmony_ci int i; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* only proceed if VMDq is enabled */ 1938c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_VMDQ_ENABLED)) 1948c2ecf20Sopenharmony_ci return false; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci /* start at VMDq register offset for SR-IOV enabled setups */ 1978c2ecf20Sopenharmony_ci pool = 0; 1988c2ecf20Sopenharmony_ci reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask); 1998c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++, reg_idx++) { 2008c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 2018c2ecf20Sopenharmony_ci /* Allow first FCoE queue to be mapped as RSS */ 2028c2ecf20Sopenharmony_ci if (fcoe->offset && (i > fcoe->offset)) 2038c2ecf20Sopenharmony_ci break; 2048c2ecf20Sopenharmony_ci#endif 2058c2ecf20Sopenharmony_ci /* If we are greater than indices move to next pool */ 2068c2ecf20Sopenharmony_ci if ((reg_idx & ~vmdq->mask) >= rss->indices) { 2078c2ecf20Sopenharmony_ci pool++; 2088c2ecf20Sopenharmony_ci reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask); 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci adapter->rx_ring[i]->reg_idx = reg_idx; 2118c2ecf20Sopenharmony_ci adapter->rx_ring[i]->netdev = pool ? NULL : adapter->netdev; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 2158c2ecf20Sopenharmony_ci /* FCoE uses a linear block of queues so just assigning 1:1 */ 2168c2ecf20Sopenharmony_ci for (; i < adapter->num_rx_queues; i++, reg_idx++) { 2178c2ecf20Sopenharmony_ci adapter->rx_ring[i]->reg_idx = reg_idx; 2188c2ecf20Sopenharmony_ci adapter->rx_ring[i]->netdev = adapter->netdev; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci#endif 2228c2ecf20Sopenharmony_ci reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask); 2238c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++, reg_idx++) { 2248c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 2258c2ecf20Sopenharmony_ci /* Allow first FCoE queue to be mapped as RSS */ 2268c2ecf20Sopenharmony_ci if (fcoe->offset && (i > fcoe->offset)) 2278c2ecf20Sopenharmony_ci break; 2288c2ecf20Sopenharmony_ci#endif 2298c2ecf20Sopenharmony_ci /* If we are greater than indices move to next pool */ 2308c2ecf20Sopenharmony_ci if ((reg_idx & rss->mask) >= rss->indices) 2318c2ecf20Sopenharmony_ci reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask); 2328c2ecf20Sopenharmony_ci adapter->tx_ring[i]->reg_idx = reg_idx; 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 2368c2ecf20Sopenharmony_ci /* FCoE uses a linear block of queues so just assigning 1:1 */ 2378c2ecf20Sopenharmony_ci for (; i < adapter->num_tx_queues; i++, reg_idx++) 2388c2ecf20Sopenharmony_ci adapter->tx_ring[i]->reg_idx = reg_idx; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci#endif 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci return true; 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci/** 2468c2ecf20Sopenharmony_ci * ixgbe_cache_ring_rss - Descriptor ring to register mapping for RSS 2478c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 2488c2ecf20Sopenharmony_ci * 2498c2ecf20Sopenharmony_ci * Cache the descriptor ring offsets for RSS to the assigned rings. 2508c2ecf20Sopenharmony_ci * 2518c2ecf20Sopenharmony_ci **/ 2528c2ecf20Sopenharmony_cistatic bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci int i, reg_idx; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 2578c2ecf20Sopenharmony_ci adapter->rx_ring[i]->reg_idx = i; 2588c2ecf20Sopenharmony_ci adapter->rx_ring[i]->netdev = adapter->netdev; 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci for (i = 0, reg_idx = 0; i < adapter->num_tx_queues; i++, reg_idx++) 2618c2ecf20Sopenharmony_ci adapter->tx_ring[i]->reg_idx = reg_idx; 2628c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_xdp_queues; i++, reg_idx++) 2638c2ecf20Sopenharmony_ci adapter->xdp_ring[i]->reg_idx = reg_idx; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci return true; 2668c2ecf20Sopenharmony_ci} 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci/** 2698c2ecf20Sopenharmony_ci * ixgbe_cache_ring_register - Descriptor ring to register mapping 2708c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 2718c2ecf20Sopenharmony_ci * 2728c2ecf20Sopenharmony_ci * Once we know the feature-set enabled for the device, we'll cache 2738c2ecf20Sopenharmony_ci * the register offset the descriptor ring is assigned to. 2748c2ecf20Sopenharmony_ci * 2758c2ecf20Sopenharmony_ci * Note, the order the various feature calls is important. It must start with 2768c2ecf20Sopenharmony_ci * the "most" features enabled at the same time, then trickle down to the 2778c2ecf20Sopenharmony_ci * least amount of features turned on at once. 2788c2ecf20Sopenharmony_ci **/ 2798c2ecf20Sopenharmony_cistatic void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) 2808c2ecf20Sopenharmony_ci{ 2818c2ecf20Sopenharmony_ci /* start with default case */ 2828c2ecf20Sopenharmony_ci adapter->rx_ring[0]->reg_idx = 0; 2838c2ecf20Sopenharmony_ci adapter->tx_ring[0]->reg_idx = 0; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci#ifdef CONFIG_IXGBE_DCB 2868c2ecf20Sopenharmony_ci if (ixgbe_cache_ring_dcb_sriov(adapter)) 2878c2ecf20Sopenharmony_ci return; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci if (ixgbe_cache_ring_dcb(adapter)) 2908c2ecf20Sopenharmony_ci return; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci#endif 2938c2ecf20Sopenharmony_ci if (ixgbe_cache_ring_sriov(adapter)) 2948c2ecf20Sopenharmony_ci return; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci ixgbe_cache_ring_rss(adapter); 2978c2ecf20Sopenharmony_ci} 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic int ixgbe_xdp_queues(struct ixgbe_adapter *adapter) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci return adapter->xdp_prog ? nr_cpu_ids : 0; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci#define IXGBE_RSS_64Q_MASK 0x3F 3058c2ecf20Sopenharmony_ci#define IXGBE_RSS_16Q_MASK 0xF 3068c2ecf20Sopenharmony_ci#define IXGBE_RSS_8Q_MASK 0x7 3078c2ecf20Sopenharmony_ci#define IXGBE_RSS_4Q_MASK 0x3 3088c2ecf20Sopenharmony_ci#define IXGBE_RSS_2Q_MASK 0x1 3098c2ecf20Sopenharmony_ci#define IXGBE_RSS_DISABLED_MASK 0x0 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci#ifdef CONFIG_IXGBE_DCB 3128c2ecf20Sopenharmony_ci/** 3138c2ecf20Sopenharmony_ci * ixgbe_set_dcb_sriov_queues: Allocate queues for SR-IOV devices w/ DCB 3148c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 3158c2ecf20Sopenharmony_ci * 3168c2ecf20Sopenharmony_ci * When SR-IOV (Single Root IO Virtualiztion) is enabled, allocate queues 3178c2ecf20Sopenharmony_ci * and VM pools where appropriate. Also assign queues based on DCB 3188c2ecf20Sopenharmony_ci * priorities and map accordingly.. 3198c2ecf20Sopenharmony_ci * 3208c2ecf20Sopenharmony_ci **/ 3218c2ecf20Sopenharmony_cistatic bool ixgbe_set_dcb_sriov_queues(struct ixgbe_adapter *adapter) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci int i; 3248c2ecf20Sopenharmony_ci u16 vmdq_i = adapter->ring_feature[RING_F_VMDQ].limit; 3258c2ecf20Sopenharmony_ci u16 vmdq_m = 0; 3268c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 3278c2ecf20Sopenharmony_ci u16 fcoe_i = 0; 3288c2ecf20Sopenharmony_ci#endif 3298c2ecf20Sopenharmony_ci u8 tcs = adapter->hw_tcs; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* verify we have DCB queueing enabled before proceeding */ 3328c2ecf20Sopenharmony_ci if (tcs <= 1) 3338c2ecf20Sopenharmony_ci return false; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* verify we have VMDq enabled before proceeding */ 3368c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) 3378c2ecf20Sopenharmony_ci return false; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* limit VMDq instances on the PF by number of Tx queues */ 3408c2ecf20Sopenharmony_ci vmdq_i = min_t(u16, vmdq_i, MAX_TX_QUEUES / tcs); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci /* Add starting offset to total pool count */ 3438c2ecf20Sopenharmony_ci vmdq_i += adapter->ring_feature[RING_F_VMDQ].offset; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* 16 pools w/ 8 TC per pool */ 3468c2ecf20Sopenharmony_ci if (tcs > 4) { 3478c2ecf20Sopenharmony_ci vmdq_i = min_t(u16, vmdq_i, 16); 3488c2ecf20Sopenharmony_ci vmdq_m = IXGBE_82599_VMDQ_8Q_MASK; 3498c2ecf20Sopenharmony_ci /* 32 pools w/ 4 TC per pool */ 3508c2ecf20Sopenharmony_ci } else { 3518c2ecf20Sopenharmony_ci vmdq_i = min_t(u16, vmdq_i, 32); 3528c2ecf20Sopenharmony_ci vmdq_m = IXGBE_82599_VMDQ_4Q_MASK; 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 3568c2ecf20Sopenharmony_ci /* queues in the remaining pools are available for FCoE */ 3578c2ecf20Sopenharmony_ci fcoe_i = (128 / __ALIGN_MASK(1, ~vmdq_m)) - vmdq_i; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci#endif 3608c2ecf20Sopenharmony_ci /* remove the starting offset from the pool count */ 3618c2ecf20Sopenharmony_ci vmdq_i -= adapter->ring_feature[RING_F_VMDQ].offset; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci /* save features for later use */ 3648c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_VMDQ].indices = vmdq_i; 3658c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_VMDQ].mask = vmdq_m; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci /* 3688c2ecf20Sopenharmony_ci * We do not support DCB, VMDq, and RSS all simultaneously 3698c2ecf20Sopenharmony_ci * so we will disable RSS since it is the lowest priority 3708c2ecf20Sopenharmony_ci */ 3718c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_RSS].indices = 1; 3728c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_RSS].mask = IXGBE_RSS_DISABLED_MASK; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci /* disable ATR as it is not supported when VMDq is enabled */ 3758c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci adapter->num_rx_pools = vmdq_i; 3788c2ecf20Sopenharmony_ci adapter->num_rx_queues_per_pool = tcs; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci adapter->num_tx_queues = vmdq_i * tcs; 3818c2ecf20Sopenharmony_ci adapter->num_xdp_queues = 0; 3828c2ecf20Sopenharmony_ci adapter->num_rx_queues = vmdq_i * tcs; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 3858c2ecf20Sopenharmony_ci if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { 3868c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *fcoe; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci fcoe = &adapter->ring_feature[RING_F_FCOE]; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci /* limit ourselves based on feature limits */ 3918c2ecf20Sopenharmony_ci fcoe_i = min_t(u16, fcoe_i, fcoe->limit); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci if (fcoe_i) { 3948c2ecf20Sopenharmony_ci /* alloc queues for FCoE separately */ 3958c2ecf20Sopenharmony_ci fcoe->indices = fcoe_i; 3968c2ecf20Sopenharmony_ci fcoe->offset = vmdq_i * tcs; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* add queues to adapter */ 3998c2ecf20Sopenharmony_ci adapter->num_tx_queues += fcoe_i; 4008c2ecf20Sopenharmony_ci adapter->num_rx_queues += fcoe_i; 4018c2ecf20Sopenharmony_ci } else if (tcs > 1) { 4028c2ecf20Sopenharmony_ci /* use queue belonging to FcoE TC */ 4038c2ecf20Sopenharmony_ci fcoe->indices = 1; 4048c2ecf20Sopenharmony_ci fcoe->offset = ixgbe_fcoe_get_tc(adapter); 4058c2ecf20Sopenharmony_ci } else { 4068c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci fcoe->indices = 0; 4098c2ecf20Sopenharmony_ci fcoe->offset = 0; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci#endif /* IXGBE_FCOE */ 4148c2ecf20Sopenharmony_ci /* configure TC to queue mapping */ 4158c2ecf20Sopenharmony_ci for (i = 0; i < tcs; i++) 4168c2ecf20Sopenharmony_ci netdev_set_tc_queue(adapter->netdev, i, 1, i); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci return true; 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci struct net_device *dev = adapter->netdev; 4248c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *f; 4258c2ecf20Sopenharmony_ci int rss_i, rss_m, i; 4268c2ecf20Sopenharmony_ci int tcs; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci /* Map queue offset and counts onto allocated tx queues */ 4298c2ecf20Sopenharmony_ci tcs = adapter->hw_tcs; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci /* verify we have DCB queueing enabled before proceeding */ 4328c2ecf20Sopenharmony_ci if (tcs <= 1) 4338c2ecf20Sopenharmony_ci return false; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci /* determine the upper limit for our current DCB mode */ 4368c2ecf20Sopenharmony_ci rss_i = dev->num_tx_queues / tcs; 4378c2ecf20Sopenharmony_ci if (adapter->hw.mac.type == ixgbe_mac_82598EB) { 4388c2ecf20Sopenharmony_ci /* 8 TC w/ 4 queues per TC */ 4398c2ecf20Sopenharmony_ci rss_i = min_t(u16, rss_i, 4); 4408c2ecf20Sopenharmony_ci rss_m = IXGBE_RSS_4Q_MASK; 4418c2ecf20Sopenharmony_ci } else if (tcs > 4) { 4428c2ecf20Sopenharmony_ci /* 8 TC w/ 8 queues per TC */ 4438c2ecf20Sopenharmony_ci rss_i = min_t(u16, rss_i, 8); 4448c2ecf20Sopenharmony_ci rss_m = IXGBE_RSS_8Q_MASK; 4458c2ecf20Sopenharmony_ci } else { 4468c2ecf20Sopenharmony_ci /* 4 TC w/ 16 queues per TC */ 4478c2ecf20Sopenharmony_ci rss_i = min_t(u16, rss_i, 16); 4488c2ecf20Sopenharmony_ci rss_m = IXGBE_RSS_16Q_MASK; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci /* set RSS mask and indices */ 4528c2ecf20Sopenharmony_ci f = &adapter->ring_feature[RING_F_RSS]; 4538c2ecf20Sopenharmony_ci rss_i = min_t(int, rss_i, f->limit); 4548c2ecf20Sopenharmony_ci f->indices = rss_i; 4558c2ecf20Sopenharmony_ci f->mask = rss_m; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci /* disable ATR as it is not supported when multiple TCs are enabled */ 4588c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 4618c2ecf20Sopenharmony_ci /* FCoE enabled queues require special configuration indexed 4628c2ecf20Sopenharmony_ci * by feature specific indices and offset. Here we map FCoE 4638c2ecf20Sopenharmony_ci * indices onto the DCB queue pairs allowing FCoE to own 4648c2ecf20Sopenharmony_ci * configuration later. 4658c2ecf20Sopenharmony_ci */ 4668c2ecf20Sopenharmony_ci if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { 4678c2ecf20Sopenharmony_ci u8 tc = ixgbe_fcoe_get_tc(adapter); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci f = &adapter->ring_feature[RING_F_FCOE]; 4708c2ecf20Sopenharmony_ci f->indices = min_t(u16, rss_i, f->limit); 4718c2ecf20Sopenharmony_ci f->offset = rss_i * tc; 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci#endif /* IXGBE_FCOE */ 4758c2ecf20Sopenharmony_ci for (i = 0; i < tcs; i++) 4768c2ecf20Sopenharmony_ci netdev_set_tc_queue(dev, i, rss_i, rss_i * i); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci adapter->num_tx_queues = rss_i * tcs; 4798c2ecf20Sopenharmony_ci adapter->num_xdp_queues = 0; 4808c2ecf20Sopenharmony_ci adapter->num_rx_queues = rss_i * tcs; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci return true; 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci#endif 4868c2ecf20Sopenharmony_ci/** 4878c2ecf20Sopenharmony_ci * ixgbe_set_sriov_queues - Allocate queues for SR-IOV devices 4888c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 4898c2ecf20Sopenharmony_ci * 4908c2ecf20Sopenharmony_ci * When SR-IOV (Single Root IO Virtualiztion) is enabled, allocate queues 4918c2ecf20Sopenharmony_ci * and VM pools where appropriate. If RSS is available, then also try and 4928c2ecf20Sopenharmony_ci * enable RSS and map accordingly. 4938c2ecf20Sopenharmony_ci * 4948c2ecf20Sopenharmony_ci **/ 4958c2ecf20Sopenharmony_cistatic bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter) 4968c2ecf20Sopenharmony_ci{ 4978c2ecf20Sopenharmony_ci u16 vmdq_i = adapter->ring_feature[RING_F_VMDQ].limit; 4988c2ecf20Sopenharmony_ci u16 vmdq_m = 0; 4998c2ecf20Sopenharmony_ci u16 rss_i = adapter->ring_feature[RING_F_RSS].limit; 5008c2ecf20Sopenharmony_ci u16 rss_m = IXGBE_RSS_DISABLED_MASK; 5018c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 5028c2ecf20Sopenharmony_ci u16 fcoe_i = 0; 5038c2ecf20Sopenharmony_ci#endif 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci /* only proceed if SR-IOV is enabled */ 5068c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) 5078c2ecf20Sopenharmony_ci return false; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci /* limit l2fwd RSS based on total Tx queue limit */ 5108c2ecf20Sopenharmony_ci rss_i = min_t(u16, rss_i, MAX_TX_QUEUES / vmdq_i); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci /* Add starting offset to total pool count */ 5138c2ecf20Sopenharmony_ci vmdq_i += adapter->ring_feature[RING_F_VMDQ].offset; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci /* double check we are limited to maximum pools */ 5168c2ecf20Sopenharmony_ci vmdq_i = min_t(u16, IXGBE_MAX_VMDQ_INDICES, vmdq_i); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci /* 64 pool mode with 2 queues per pool */ 5198c2ecf20Sopenharmony_ci if (vmdq_i > 32) { 5208c2ecf20Sopenharmony_ci vmdq_m = IXGBE_82599_VMDQ_2Q_MASK; 5218c2ecf20Sopenharmony_ci rss_m = IXGBE_RSS_2Q_MASK; 5228c2ecf20Sopenharmony_ci rss_i = min_t(u16, rss_i, 2); 5238c2ecf20Sopenharmony_ci /* 32 pool mode with up to 4 queues per pool */ 5248c2ecf20Sopenharmony_ci } else { 5258c2ecf20Sopenharmony_ci vmdq_m = IXGBE_82599_VMDQ_4Q_MASK; 5268c2ecf20Sopenharmony_ci rss_m = IXGBE_RSS_4Q_MASK; 5278c2ecf20Sopenharmony_ci /* We can support 4, 2, or 1 queues */ 5288c2ecf20Sopenharmony_ci rss_i = (rss_i > 3) ? 4 : (rss_i > 1) ? 2 : 1; 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 5328c2ecf20Sopenharmony_ci /* queues in the remaining pools are available for FCoE */ 5338c2ecf20Sopenharmony_ci fcoe_i = 128 - (vmdq_i * __ALIGN_MASK(1, ~vmdq_m)); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci#endif 5368c2ecf20Sopenharmony_ci /* remove the starting offset from the pool count */ 5378c2ecf20Sopenharmony_ci vmdq_i -= adapter->ring_feature[RING_F_VMDQ].offset; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci /* save features for later use */ 5408c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_VMDQ].indices = vmdq_i; 5418c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_VMDQ].mask = vmdq_m; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci /* limit RSS based on user input and save for later use */ 5448c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_RSS].indices = rss_i; 5458c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_RSS].mask = rss_m; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci adapter->num_rx_pools = vmdq_i; 5488c2ecf20Sopenharmony_ci adapter->num_rx_queues_per_pool = rss_i; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci adapter->num_rx_queues = vmdq_i * rss_i; 5518c2ecf20Sopenharmony_ci adapter->num_tx_queues = vmdq_i * rss_i; 5528c2ecf20Sopenharmony_ci adapter->num_xdp_queues = 0; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* disable ATR as it is not supported when VMDq is enabled */ 5558c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 5588c2ecf20Sopenharmony_ci /* 5598c2ecf20Sopenharmony_ci * FCoE can use rings from adjacent buffers to allow RSS 5608c2ecf20Sopenharmony_ci * like behavior. To account for this we need to add the 5618c2ecf20Sopenharmony_ci * FCoE indices to the total ring count. 5628c2ecf20Sopenharmony_ci */ 5638c2ecf20Sopenharmony_ci if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { 5648c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *fcoe; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci fcoe = &adapter->ring_feature[RING_F_FCOE]; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci /* limit ourselves based on feature limits */ 5698c2ecf20Sopenharmony_ci fcoe_i = min_t(u16, fcoe_i, fcoe->limit); 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci if (vmdq_i > 1 && fcoe_i) { 5728c2ecf20Sopenharmony_ci /* alloc queues for FCoE separately */ 5738c2ecf20Sopenharmony_ci fcoe->indices = fcoe_i; 5748c2ecf20Sopenharmony_ci fcoe->offset = vmdq_i * rss_i; 5758c2ecf20Sopenharmony_ci } else { 5768c2ecf20Sopenharmony_ci /* merge FCoE queues with RSS queues */ 5778c2ecf20Sopenharmony_ci fcoe_i = min_t(u16, fcoe_i + rss_i, num_online_cpus()); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci /* limit indices to rss_i if MSI-X is disabled */ 5808c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) 5818c2ecf20Sopenharmony_ci fcoe_i = rss_i; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci /* attempt to reserve some queues for just FCoE */ 5848c2ecf20Sopenharmony_ci fcoe->indices = min_t(u16, fcoe_i, fcoe->limit); 5858c2ecf20Sopenharmony_ci fcoe->offset = fcoe_i - fcoe->indices; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci fcoe_i -= rss_i; 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci /* add queues to adapter */ 5918c2ecf20Sopenharmony_ci adapter->num_tx_queues += fcoe_i; 5928c2ecf20Sopenharmony_ci adapter->num_rx_queues += fcoe_i; 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci#endif 5968c2ecf20Sopenharmony_ci /* To support macvlan offload we have to use num_tc to 5978c2ecf20Sopenharmony_ci * restrict the queues that can be used by the device. 5988c2ecf20Sopenharmony_ci * By doing this we can avoid reporting a false number of 5998c2ecf20Sopenharmony_ci * queues. 6008c2ecf20Sopenharmony_ci */ 6018c2ecf20Sopenharmony_ci if (vmdq_i > 1) 6028c2ecf20Sopenharmony_ci netdev_set_num_tc(adapter->netdev, 1); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* populate TC0 for use by pool 0 */ 6058c2ecf20Sopenharmony_ci netdev_set_tc_queue(adapter->netdev, 0, 6068c2ecf20Sopenharmony_ci adapter->num_rx_queues_per_pool, 0); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci return true; 6098c2ecf20Sopenharmony_ci} 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci/** 6128c2ecf20Sopenharmony_ci * ixgbe_set_rss_queues - Allocate queues for RSS 6138c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 6148c2ecf20Sopenharmony_ci * 6158c2ecf20Sopenharmony_ci * This is our "base" multiqueue mode. RSS (Receive Side Scaling) will try 6168c2ecf20Sopenharmony_ci * to allocate one Rx queue per CPU, and if available, one Tx queue per CPU. 6178c2ecf20Sopenharmony_ci * 6188c2ecf20Sopenharmony_ci **/ 6198c2ecf20Sopenharmony_cistatic bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) 6208c2ecf20Sopenharmony_ci{ 6218c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 6228c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *f; 6238c2ecf20Sopenharmony_ci u16 rss_i; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci /* set mask for 16 queue limit of RSS */ 6268c2ecf20Sopenharmony_ci f = &adapter->ring_feature[RING_F_RSS]; 6278c2ecf20Sopenharmony_ci rss_i = f->limit; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci f->indices = rss_i; 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci if (hw->mac.type < ixgbe_mac_X550) 6328c2ecf20Sopenharmony_ci f->mask = IXGBE_RSS_16Q_MASK; 6338c2ecf20Sopenharmony_ci else 6348c2ecf20Sopenharmony_ci f->mask = IXGBE_RSS_64Q_MASK; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci /* disable ATR by default, it will be configured below */ 6378c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci /* 6408c2ecf20Sopenharmony_ci * Use Flow Director in addition to RSS to ensure the best 6418c2ecf20Sopenharmony_ci * distribution of flows across cores, even when an FDIR flow 6428c2ecf20Sopenharmony_ci * isn't matched. 6438c2ecf20Sopenharmony_ci */ 6448c2ecf20Sopenharmony_ci if (rss_i > 1 && adapter->atr_sample_rate) { 6458c2ecf20Sopenharmony_ci f = &adapter->ring_feature[RING_F_FDIR]; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci rss_i = f->indices = f->limit; 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) 6508c2ecf20Sopenharmony_ci adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; 6518c2ecf20Sopenharmony_ci } 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 6548c2ecf20Sopenharmony_ci /* 6558c2ecf20Sopenharmony_ci * FCoE can exist on the same rings as standard network traffic 6568c2ecf20Sopenharmony_ci * however it is preferred to avoid that if possible. In order 6578c2ecf20Sopenharmony_ci * to get the best performance we allocate as many FCoE queues 6588c2ecf20Sopenharmony_ci * as we can and we place them at the end of the ring array to 6598c2ecf20Sopenharmony_ci * avoid sharing queues with standard RSS on systems with 24 or 6608c2ecf20Sopenharmony_ci * more CPUs. 6618c2ecf20Sopenharmony_ci */ 6628c2ecf20Sopenharmony_ci if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { 6638c2ecf20Sopenharmony_ci struct net_device *dev = adapter->netdev; 6648c2ecf20Sopenharmony_ci u16 fcoe_i; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci f = &adapter->ring_feature[RING_F_FCOE]; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci /* merge FCoE queues with RSS queues */ 6698c2ecf20Sopenharmony_ci fcoe_i = min_t(u16, f->limit + rss_i, num_online_cpus()); 6708c2ecf20Sopenharmony_ci fcoe_i = min_t(u16, fcoe_i, dev->num_tx_queues); 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci /* limit indices to rss_i if MSI-X is disabled */ 6738c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) 6748c2ecf20Sopenharmony_ci fcoe_i = rss_i; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci /* attempt to reserve some queues for just FCoE */ 6778c2ecf20Sopenharmony_ci f->indices = min_t(u16, fcoe_i, f->limit); 6788c2ecf20Sopenharmony_ci f->offset = fcoe_i - f->indices; 6798c2ecf20Sopenharmony_ci rss_i = max_t(u16, fcoe_i, rss_i); 6808c2ecf20Sopenharmony_ci } 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci#endif /* IXGBE_FCOE */ 6838c2ecf20Sopenharmony_ci adapter->num_rx_queues = rss_i; 6848c2ecf20Sopenharmony_ci adapter->num_tx_queues = rss_i; 6858c2ecf20Sopenharmony_ci adapter->num_xdp_queues = ixgbe_xdp_queues(adapter); 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci return true; 6888c2ecf20Sopenharmony_ci} 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci/** 6918c2ecf20Sopenharmony_ci * ixgbe_set_num_queues - Allocate queues for device, feature dependent 6928c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 6938c2ecf20Sopenharmony_ci * 6948c2ecf20Sopenharmony_ci * This is the top level queue allocation routine. The order here is very 6958c2ecf20Sopenharmony_ci * important, starting with the "most" number of features turned on at once, 6968c2ecf20Sopenharmony_ci * and ending with the smallest set of features. This way large combinations 6978c2ecf20Sopenharmony_ci * can be allocated if they're turned on, and smaller combinations are the 6988c2ecf20Sopenharmony_ci * fallthrough conditions. 6998c2ecf20Sopenharmony_ci * 7008c2ecf20Sopenharmony_ci **/ 7018c2ecf20Sopenharmony_cistatic void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci /* Start with base case */ 7048c2ecf20Sopenharmony_ci adapter->num_rx_queues = 1; 7058c2ecf20Sopenharmony_ci adapter->num_tx_queues = 1; 7068c2ecf20Sopenharmony_ci adapter->num_xdp_queues = 0; 7078c2ecf20Sopenharmony_ci adapter->num_rx_pools = 1; 7088c2ecf20Sopenharmony_ci adapter->num_rx_queues_per_pool = 1; 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci#ifdef CONFIG_IXGBE_DCB 7118c2ecf20Sopenharmony_ci if (ixgbe_set_dcb_sriov_queues(adapter)) 7128c2ecf20Sopenharmony_ci return; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci if (ixgbe_set_dcb_queues(adapter)) 7158c2ecf20Sopenharmony_ci return; 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci#endif 7188c2ecf20Sopenharmony_ci if (ixgbe_set_sriov_queues(adapter)) 7198c2ecf20Sopenharmony_ci return; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci ixgbe_set_rss_queues(adapter); 7228c2ecf20Sopenharmony_ci} 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci/** 7258c2ecf20Sopenharmony_ci * ixgbe_acquire_msix_vectors - acquire MSI-X vectors 7268c2ecf20Sopenharmony_ci * @adapter: board private structure 7278c2ecf20Sopenharmony_ci * 7288c2ecf20Sopenharmony_ci * Attempts to acquire a suitable range of MSI-X vector interrupts. Will 7298c2ecf20Sopenharmony_ci * return a negative error code if unable to acquire MSI-X vectors for any 7308c2ecf20Sopenharmony_ci * reason. 7318c2ecf20Sopenharmony_ci */ 7328c2ecf20Sopenharmony_cistatic int ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter) 7338c2ecf20Sopenharmony_ci{ 7348c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 7358c2ecf20Sopenharmony_ci int i, vectors, vector_threshold; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci /* We start by asking for one vector per queue pair with XDP queues 7388c2ecf20Sopenharmony_ci * being stacked with TX queues. 7398c2ecf20Sopenharmony_ci */ 7408c2ecf20Sopenharmony_ci vectors = max(adapter->num_rx_queues, adapter->num_tx_queues); 7418c2ecf20Sopenharmony_ci vectors = max(vectors, adapter->num_xdp_queues); 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci /* It is easy to be greedy for MSI-X vectors. However, it really 7448c2ecf20Sopenharmony_ci * doesn't do much good if we have a lot more vectors than CPUs. We'll 7458c2ecf20Sopenharmony_ci * be somewhat conservative and only ask for (roughly) the same number 7468c2ecf20Sopenharmony_ci * of vectors as there are CPUs. 7478c2ecf20Sopenharmony_ci */ 7488c2ecf20Sopenharmony_ci vectors = min_t(int, vectors, num_online_cpus()); 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci /* Some vectors are necessary for non-queue interrupts */ 7518c2ecf20Sopenharmony_ci vectors += NON_Q_VECTORS; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci /* Hardware can only support a maximum of hw.mac->max_msix_vectors. 7548c2ecf20Sopenharmony_ci * With features such as RSS and VMDq, we can easily surpass the 7558c2ecf20Sopenharmony_ci * number of Rx and Tx descriptor queues supported by our device. 7568c2ecf20Sopenharmony_ci * Thus, we cap the maximum in the rare cases where the CPU count also 7578c2ecf20Sopenharmony_ci * exceeds our vector limit 7588c2ecf20Sopenharmony_ci */ 7598c2ecf20Sopenharmony_ci vectors = min_t(int, vectors, hw->mac.max_msix_vectors); 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci /* We want a minimum of two MSI-X vectors for (1) a TxQ[0] + RxQ[0] 7628c2ecf20Sopenharmony_ci * handler, and (2) an Other (Link Status Change, etc.) handler. 7638c2ecf20Sopenharmony_ci */ 7648c2ecf20Sopenharmony_ci vector_threshold = MIN_MSIX_COUNT; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci adapter->msix_entries = kcalloc(vectors, 7678c2ecf20Sopenharmony_ci sizeof(struct msix_entry), 7688c2ecf20Sopenharmony_ci GFP_KERNEL); 7698c2ecf20Sopenharmony_ci if (!adapter->msix_entries) 7708c2ecf20Sopenharmony_ci return -ENOMEM; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci for (i = 0; i < vectors; i++) 7738c2ecf20Sopenharmony_ci adapter->msix_entries[i].entry = i; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci vectors = pci_enable_msix_range(adapter->pdev, adapter->msix_entries, 7768c2ecf20Sopenharmony_ci vector_threshold, vectors); 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci if (vectors < 0) { 7798c2ecf20Sopenharmony_ci /* A negative count of allocated vectors indicates an error in 7808c2ecf20Sopenharmony_ci * acquiring within the specified range of MSI-X vectors 7818c2ecf20Sopenharmony_ci */ 7828c2ecf20Sopenharmony_ci e_dev_warn("Failed to allocate MSI-X interrupts. Err: %d\n", 7838c2ecf20Sopenharmony_ci vectors); 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; 7868c2ecf20Sopenharmony_ci kfree(adapter->msix_entries); 7878c2ecf20Sopenharmony_ci adapter->msix_entries = NULL; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci return vectors; 7908c2ecf20Sopenharmony_ci } 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci /* we successfully allocated some number of vectors within our 7938c2ecf20Sopenharmony_ci * requested range. 7948c2ecf20Sopenharmony_ci */ 7958c2ecf20Sopenharmony_ci adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci /* Adjust for only the vectors we'll use, which is minimum 7988c2ecf20Sopenharmony_ci * of max_q_vectors, or the number of vectors we were allocated. 7998c2ecf20Sopenharmony_ci */ 8008c2ecf20Sopenharmony_ci vectors -= NON_Q_VECTORS; 8018c2ecf20Sopenharmony_ci adapter->num_q_vectors = min_t(int, vectors, adapter->max_q_vectors); 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci return 0; 8048c2ecf20Sopenharmony_ci} 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_cistatic void ixgbe_add_ring(struct ixgbe_ring *ring, 8078c2ecf20Sopenharmony_ci struct ixgbe_ring_container *head) 8088c2ecf20Sopenharmony_ci{ 8098c2ecf20Sopenharmony_ci ring->next = head->ring; 8108c2ecf20Sopenharmony_ci head->ring = ring; 8118c2ecf20Sopenharmony_ci head->count++; 8128c2ecf20Sopenharmony_ci head->next_update = jiffies + 1; 8138c2ecf20Sopenharmony_ci} 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci/** 8168c2ecf20Sopenharmony_ci * ixgbe_alloc_q_vector - Allocate memory for a single interrupt vector 8178c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 8188c2ecf20Sopenharmony_ci * @v_count: q_vectors allocated on adapter, used for ring interleaving 8198c2ecf20Sopenharmony_ci * @v_idx: index of vector in adapter struct 8208c2ecf20Sopenharmony_ci * @txr_count: total number of Tx rings to allocate 8218c2ecf20Sopenharmony_ci * @txr_idx: index of first Tx ring to allocate 8228c2ecf20Sopenharmony_ci * @xdp_count: total number of XDP rings to allocate 8238c2ecf20Sopenharmony_ci * @xdp_idx: index of first XDP ring to allocate 8248c2ecf20Sopenharmony_ci * @rxr_count: total number of Rx rings to allocate 8258c2ecf20Sopenharmony_ci * @rxr_idx: index of first Rx ring to allocate 8268c2ecf20Sopenharmony_ci * 8278c2ecf20Sopenharmony_ci * We allocate one q_vector. If allocation fails we return -ENOMEM. 8288c2ecf20Sopenharmony_ci **/ 8298c2ecf20Sopenharmony_cistatic int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, 8308c2ecf20Sopenharmony_ci int v_count, int v_idx, 8318c2ecf20Sopenharmony_ci int txr_count, int txr_idx, 8328c2ecf20Sopenharmony_ci int xdp_count, int xdp_idx, 8338c2ecf20Sopenharmony_ci int rxr_count, int rxr_idx) 8348c2ecf20Sopenharmony_ci{ 8358c2ecf20Sopenharmony_ci int node = dev_to_node(&adapter->pdev->dev); 8368c2ecf20Sopenharmony_ci struct ixgbe_q_vector *q_vector; 8378c2ecf20Sopenharmony_ci struct ixgbe_ring *ring; 8388c2ecf20Sopenharmony_ci int cpu = -1; 8398c2ecf20Sopenharmony_ci int ring_count; 8408c2ecf20Sopenharmony_ci u8 tcs = adapter->hw_tcs; 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci ring_count = txr_count + rxr_count + xdp_count; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci /* customize cpu for Flow Director mapping */ 8458c2ecf20Sopenharmony_ci if ((tcs <= 1) && !(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) { 8468c2ecf20Sopenharmony_ci u16 rss_i = adapter->ring_feature[RING_F_RSS].indices; 8478c2ecf20Sopenharmony_ci if (rss_i > 1 && adapter->atr_sample_rate) { 8488c2ecf20Sopenharmony_ci cpu = cpumask_local_spread(v_idx, node); 8498c2ecf20Sopenharmony_ci node = cpu_to_node(cpu); 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci /* allocate q_vector and rings */ 8548c2ecf20Sopenharmony_ci q_vector = kzalloc_node(struct_size(q_vector, ring, ring_count), 8558c2ecf20Sopenharmony_ci GFP_KERNEL, node); 8568c2ecf20Sopenharmony_ci if (!q_vector) 8578c2ecf20Sopenharmony_ci q_vector = kzalloc(struct_size(q_vector, ring, ring_count), 8588c2ecf20Sopenharmony_ci GFP_KERNEL); 8598c2ecf20Sopenharmony_ci if (!q_vector) 8608c2ecf20Sopenharmony_ci return -ENOMEM; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci /* setup affinity mask and node */ 8638c2ecf20Sopenharmony_ci if (cpu != -1) 8648c2ecf20Sopenharmony_ci cpumask_set_cpu(cpu, &q_vector->affinity_mask); 8658c2ecf20Sopenharmony_ci q_vector->numa_node = node; 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci#ifdef CONFIG_IXGBE_DCA 8688c2ecf20Sopenharmony_ci /* initialize CPU for DCA */ 8698c2ecf20Sopenharmony_ci q_vector->cpu = -1; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci#endif 8728c2ecf20Sopenharmony_ci /* initialize NAPI */ 8738c2ecf20Sopenharmony_ci netif_napi_add(adapter->netdev, &q_vector->napi, 8748c2ecf20Sopenharmony_ci ixgbe_poll, 64); 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci /* tie q_vector and adapter together */ 8778c2ecf20Sopenharmony_ci adapter->q_vector[v_idx] = q_vector; 8788c2ecf20Sopenharmony_ci q_vector->adapter = adapter; 8798c2ecf20Sopenharmony_ci q_vector->v_idx = v_idx; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci /* initialize work limits */ 8828c2ecf20Sopenharmony_ci q_vector->tx.work_limit = adapter->tx_work_limit; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci /* Initialize setting for adaptive ITR */ 8858c2ecf20Sopenharmony_ci q_vector->tx.itr = IXGBE_ITR_ADAPTIVE_MAX_USECS | 8868c2ecf20Sopenharmony_ci IXGBE_ITR_ADAPTIVE_LATENCY; 8878c2ecf20Sopenharmony_ci q_vector->rx.itr = IXGBE_ITR_ADAPTIVE_MAX_USECS | 8888c2ecf20Sopenharmony_ci IXGBE_ITR_ADAPTIVE_LATENCY; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci /* intialize ITR */ 8918c2ecf20Sopenharmony_ci if (txr_count && !rxr_count) { 8928c2ecf20Sopenharmony_ci /* tx only vector */ 8938c2ecf20Sopenharmony_ci if (adapter->tx_itr_setting == 1) 8948c2ecf20Sopenharmony_ci q_vector->itr = IXGBE_12K_ITR; 8958c2ecf20Sopenharmony_ci else 8968c2ecf20Sopenharmony_ci q_vector->itr = adapter->tx_itr_setting; 8978c2ecf20Sopenharmony_ci } else { 8988c2ecf20Sopenharmony_ci /* rx or rx/tx vector */ 8998c2ecf20Sopenharmony_ci if (adapter->rx_itr_setting == 1) 9008c2ecf20Sopenharmony_ci q_vector->itr = IXGBE_20K_ITR; 9018c2ecf20Sopenharmony_ci else 9028c2ecf20Sopenharmony_ci q_vector->itr = adapter->rx_itr_setting; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci /* initialize pointer to rings */ 9068c2ecf20Sopenharmony_ci ring = q_vector->ring; 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci while (txr_count) { 9098c2ecf20Sopenharmony_ci /* assign generic ring traits */ 9108c2ecf20Sopenharmony_ci ring->dev = &adapter->pdev->dev; 9118c2ecf20Sopenharmony_ci ring->netdev = adapter->netdev; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci /* configure backlink on ring */ 9148c2ecf20Sopenharmony_ci ring->q_vector = q_vector; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci /* update q_vector Tx values */ 9178c2ecf20Sopenharmony_ci ixgbe_add_ring(ring, &q_vector->tx); 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci /* apply Tx specific ring traits */ 9208c2ecf20Sopenharmony_ci ring->count = adapter->tx_ring_count; 9218c2ecf20Sopenharmony_ci ring->queue_index = txr_idx; 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci /* assign ring to adapter */ 9248c2ecf20Sopenharmony_ci WRITE_ONCE(adapter->tx_ring[txr_idx], ring); 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci /* update count and index */ 9278c2ecf20Sopenharmony_ci txr_count--; 9288c2ecf20Sopenharmony_ci txr_idx += v_count; 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci /* push pointer to next ring */ 9318c2ecf20Sopenharmony_ci ring++; 9328c2ecf20Sopenharmony_ci } 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci while (xdp_count) { 9358c2ecf20Sopenharmony_ci /* assign generic ring traits */ 9368c2ecf20Sopenharmony_ci ring->dev = &adapter->pdev->dev; 9378c2ecf20Sopenharmony_ci ring->netdev = adapter->netdev; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci /* configure backlink on ring */ 9408c2ecf20Sopenharmony_ci ring->q_vector = q_vector; 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci /* update q_vector Tx values */ 9438c2ecf20Sopenharmony_ci ixgbe_add_ring(ring, &q_vector->tx); 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci /* apply Tx specific ring traits */ 9468c2ecf20Sopenharmony_ci ring->count = adapter->tx_ring_count; 9478c2ecf20Sopenharmony_ci ring->queue_index = xdp_idx; 9488c2ecf20Sopenharmony_ci set_ring_xdp(ring); 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci /* assign ring to adapter */ 9518c2ecf20Sopenharmony_ci WRITE_ONCE(adapter->xdp_ring[xdp_idx], ring); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci /* update count and index */ 9548c2ecf20Sopenharmony_ci xdp_count--; 9558c2ecf20Sopenharmony_ci xdp_idx++; 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci /* push pointer to next ring */ 9588c2ecf20Sopenharmony_ci ring++; 9598c2ecf20Sopenharmony_ci } 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci while (rxr_count) { 9628c2ecf20Sopenharmony_ci /* assign generic ring traits */ 9638c2ecf20Sopenharmony_ci ring->dev = &adapter->pdev->dev; 9648c2ecf20Sopenharmony_ci ring->netdev = adapter->netdev; 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci /* configure backlink on ring */ 9678c2ecf20Sopenharmony_ci ring->q_vector = q_vector; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci /* update q_vector Rx values */ 9708c2ecf20Sopenharmony_ci ixgbe_add_ring(ring, &q_vector->rx); 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci /* 9738c2ecf20Sopenharmony_ci * 82599 errata, UDP frames with a 0 checksum 9748c2ecf20Sopenharmony_ci * can be marked as checksum errors. 9758c2ecf20Sopenharmony_ci */ 9768c2ecf20Sopenharmony_ci if (adapter->hw.mac.type == ixgbe_mac_82599EB) 9778c2ecf20Sopenharmony_ci set_bit(__IXGBE_RX_CSUM_UDP_ZERO_ERR, &ring->state); 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 9808c2ecf20Sopenharmony_ci if (adapter->netdev->features & NETIF_F_FCOE_MTU) { 9818c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *f; 9828c2ecf20Sopenharmony_ci f = &adapter->ring_feature[RING_F_FCOE]; 9838c2ecf20Sopenharmony_ci if ((rxr_idx >= f->offset) && 9848c2ecf20Sopenharmony_ci (rxr_idx < f->offset + f->indices)) 9858c2ecf20Sopenharmony_ci set_bit(__IXGBE_RX_FCOE, &ring->state); 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci#endif /* IXGBE_FCOE */ 9898c2ecf20Sopenharmony_ci /* apply Rx specific ring traits */ 9908c2ecf20Sopenharmony_ci ring->count = adapter->rx_ring_count; 9918c2ecf20Sopenharmony_ci ring->queue_index = rxr_idx; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci /* assign ring to adapter */ 9948c2ecf20Sopenharmony_ci WRITE_ONCE(adapter->rx_ring[rxr_idx], ring); 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci /* update count and index */ 9978c2ecf20Sopenharmony_ci rxr_count--; 9988c2ecf20Sopenharmony_ci rxr_idx += v_count; 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci /* push pointer to next ring */ 10018c2ecf20Sopenharmony_ci ring++; 10028c2ecf20Sopenharmony_ci } 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci return 0; 10058c2ecf20Sopenharmony_ci} 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci/** 10088c2ecf20Sopenharmony_ci * ixgbe_free_q_vector - Free memory allocated for specific interrupt vector 10098c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 10108c2ecf20Sopenharmony_ci * @v_idx: Index of vector to be freed 10118c2ecf20Sopenharmony_ci * 10128c2ecf20Sopenharmony_ci * This function frees the memory allocated to the q_vector. In addition if 10138c2ecf20Sopenharmony_ci * NAPI is enabled it will delete any references to the NAPI struct prior 10148c2ecf20Sopenharmony_ci * to freeing the q_vector. 10158c2ecf20Sopenharmony_ci **/ 10168c2ecf20Sopenharmony_cistatic void ixgbe_free_q_vector(struct ixgbe_adapter *adapter, int v_idx) 10178c2ecf20Sopenharmony_ci{ 10188c2ecf20Sopenharmony_ci struct ixgbe_q_vector *q_vector = adapter->q_vector[v_idx]; 10198c2ecf20Sopenharmony_ci struct ixgbe_ring *ring; 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci ixgbe_for_each_ring(ring, q_vector->tx) { 10228c2ecf20Sopenharmony_ci if (ring_is_xdp(ring)) 10238c2ecf20Sopenharmony_ci WRITE_ONCE(adapter->xdp_ring[ring->queue_index], NULL); 10248c2ecf20Sopenharmony_ci else 10258c2ecf20Sopenharmony_ci WRITE_ONCE(adapter->tx_ring[ring->queue_index], NULL); 10268c2ecf20Sopenharmony_ci } 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci ixgbe_for_each_ring(ring, q_vector->rx) 10298c2ecf20Sopenharmony_ci WRITE_ONCE(adapter->rx_ring[ring->queue_index], NULL); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci adapter->q_vector[v_idx] = NULL; 10328c2ecf20Sopenharmony_ci __netif_napi_del(&q_vector->napi); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci /* 10358c2ecf20Sopenharmony_ci * after a call to __netif_napi_del() napi may still be used and 10368c2ecf20Sopenharmony_ci * ixgbe_get_stats64() might access the rings on this vector, 10378c2ecf20Sopenharmony_ci * we must wait a grace period before freeing it. 10388c2ecf20Sopenharmony_ci */ 10398c2ecf20Sopenharmony_ci kfree_rcu(q_vector, rcu); 10408c2ecf20Sopenharmony_ci} 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci/** 10438c2ecf20Sopenharmony_ci * ixgbe_alloc_q_vectors - Allocate memory for interrupt vectors 10448c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 10458c2ecf20Sopenharmony_ci * 10468c2ecf20Sopenharmony_ci * We allocate one q_vector per queue interrupt. If allocation fails we 10478c2ecf20Sopenharmony_ci * return -ENOMEM. 10488c2ecf20Sopenharmony_ci **/ 10498c2ecf20Sopenharmony_cistatic int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) 10508c2ecf20Sopenharmony_ci{ 10518c2ecf20Sopenharmony_ci int q_vectors = adapter->num_q_vectors; 10528c2ecf20Sopenharmony_ci int rxr_remaining = adapter->num_rx_queues; 10538c2ecf20Sopenharmony_ci int txr_remaining = adapter->num_tx_queues; 10548c2ecf20Sopenharmony_ci int xdp_remaining = adapter->num_xdp_queues; 10558c2ecf20Sopenharmony_ci int rxr_idx = 0, txr_idx = 0, xdp_idx = 0, v_idx = 0; 10568c2ecf20Sopenharmony_ci int err, i; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci /* only one q_vector if MSI-X is disabled. */ 10598c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) 10608c2ecf20Sopenharmony_ci q_vectors = 1; 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci if (q_vectors >= (rxr_remaining + txr_remaining + xdp_remaining)) { 10638c2ecf20Sopenharmony_ci for (; rxr_remaining; v_idx++) { 10648c2ecf20Sopenharmony_ci err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx, 10658c2ecf20Sopenharmony_ci 0, 0, 0, 0, 1, rxr_idx); 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci if (err) 10688c2ecf20Sopenharmony_ci goto err_out; 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci /* update counts and index */ 10718c2ecf20Sopenharmony_ci rxr_remaining--; 10728c2ecf20Sopenharmony_ci rxr_idx++; 10738c2ecf20Sopenharmony_ci } 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci for (; v_idx < q_vectors; v_idx++) { 10778c2ecf20Sopenharmony_ci int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx); 10788c2ecf20Sopenharmony_ci int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx); 10798c2ecf20Sopenharmony_ci int xqpv = DIV_ROUND_UP(xdp_remaining, q_vectors - v_idx); 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx, 10828c2ecf20Sopenharmony_ci tqpv, txr_idx, 10838c2ecf20Sopenharmony_ci xqpv, xdp_idx, 10848c2ecf20Sopenharmony_ci rqpv, rxr_idx); 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci if (err) 10878c2ecf20Sopenharmony_ci goto err_out; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci /* update counts and index */ 10908c2ecf20Sopenharmony_ci rxr_remaining -= rqpv; 10918c2ecf20Sopenharmony_ci txr_remaining -= tqpv; 10928c2ecf20Sopenharmony_ci xdp_remaining -= xqpv; 10938c2ecf20Sopenharmony_ci rxr_idx++; 10948c2ecf20Sopenharmony_ci txr_idx++; 10958c2ecf20Sopenharmony_ci xdp_idx += xqpv; 10968c2ecf20Sopenharmony_ci } 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 10998c2ecf20Sopenharmony_ci if (adapter->rx_ring[i]) 11008c2ecf20Sopenharmony_ci adapter->rx_ring[i]->ring_idx = i; 11018c2ecf20Sopenharmony_ci } 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 11048c2ecf20Sopenharmony_ci if (adapter->tx_ring[i]) 11058c2ecf20Sopenharmony_ci adapter->tx_ring[i]->ring_idx = i; 11068c2ecf20Sopenharmony_ci } 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_xdp_queues; i++) { 11098c2ecf20Sopenharmony_ci if (adapter->xdp_ring[i]) 11108c2ecf20Sopenharmony_ci adapter->xdp_ring[i]->ring_idx = i; 11118c2ecf20Sopenharmony_ci } 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci return 0; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_cierr_out: 11168c2ecf20Sopenharmony_ci adapter->num_tx_queues = 0; 11178c2ecf20Sopenharmony_ci adapter->num_xdp_queues = 0; 11188c2ecf20Sopenharmony_ci adapter->num_rx_queues = 0; 11198c2ecf20Sopenharmony_ci adapter->num_q_vectors = 0; 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci while (v_idx--) 11228c2ecf20Sopenharmony_ci ixgbe_free_q_vector(adapter, v_idx); 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci return -ENOMEM; 11258c2ecf20Sopenharmony_ci} 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci/** 11288c2ecf20Sopenharmony_ci * ixgbe_free_q_vectors - Free memory allocated for interrupt vectors 11298c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 11308c2ecf20Sopenharmony_ci * 11318c2ecf20Sopenharmony_ci * This function frees the memory allocated to the q_vectors. In addition if 11328c2ecf20Sopenharmony_ci * NAPI is enabled it will delete any references to the NAPI struct prior 11338c2ecf20Sopenharmony_ci * to freeing the q_vector. 11348c2ecf20Sopenharmony_ci **/ 11358c2ecf20Sopenharmony_cistatic void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter) 11368c2ecf20Sopenharmony_ci{ 11378c2ecf20Sopenharmony_ci int v_idx = adapter->num_q_vectors; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci adapter->num_tx_queues = 0; 11408c2ecf20Sopenharmony_ci adapter->num_xdp_queues = 0; 11418c2ecf20Sopenharmony_ci adapter->num_rx_queues = 0; 11428c2ecf20Sopenharmony_ci adapter->num_q_vectors = 0; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci while (v_idx--) 11458c2ecf20Sopenharmony_ci ixgbe_free_q_vector(adapter, v_idx); 11468c2ecf20Sopenharmony_ci} 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_cistatic void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter) 11498c2ecf20Sopenharmony_ci{ 11508c2ecf20Sopenharmony_ci if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { 11518c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; 11528c2ecf20Sopenharmony_ci pci_disable_msix(adapter->pdev); 11538c2ecf20Sopenharmony_ci kfree(adapter->msix_entries); 11548c2ecf20Sopenharmony_ci adapter->msix_entries = NULL; 11558c2ecf20Sopenharmony_ci } else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) { 11568c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_MSI_ENABLED; 11578c2ecf20Sopenharmony_ci pci_disable_msi(adapter->pdev); 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci} 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci/** 11628c2ecf20Sopenharmony_ci * ixgbe_set_interrupt_capability - set MSI-X or MSI if supported 11638c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 11648c2ecf20Sopenharmony_ci * 11658c2ecf20Sopenharmony_ci * Attempt to configure the interrupts using the best available 11668c2ecf20Sopenharmony_ci * capabilities of the hardware and the kernel. 11678c2ecf20Sopenharmony_ci **/ 11688c2ecf20Sopenharmony_cistatic void ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci int err; 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci /* We will try to get MSI-X interrupts first */ 11738c2ecf20Sopenharmony_ci if (!ixgbe_acquire_msix_vectors(adapter)) 11748c2ecf20Sopenharmony_ci return; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci /* At this point, we do not have MSI-X capabilities. We need to 11778c2ecf20Sopenharmony_ci * reconfigure or disable various features which require MSI-X 11788c2ecf20Sopenharmony_ci * capability. 11798c2ecf20Sopenharmony_ci */ 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci /* Disable DCB unless we only have a single traffic class */ 11828c2ecf20Sopenharmony_ci if (adapter->hw_tcs > 1) { 11838c2ecf20Sopenharmony_ci e_dev_warn("Number of DCB TCs exceeds number of available queues. Disabling DCB support.\n"); 11848c2ecf20Sopenharmony_ci netdev_reset_tc(adapter->netdev); 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci if (adapter->hw.mac.type == ixgbe_mac_82598EB) 11878c2ecf20Sopenharmony_ci adapter->hw.fc.requested_mode = adapter->last_lfc_mode; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; 11908c2ecf20Sopenharmony_ci adapter->temp_dcb_cfg.pfc_mode_enable = false; 11918c2ecf20Sopenharmony_ci adapter->dcb_cfg.pfc_mode_enable = false; 11928c2ecf20Sopenharmony_ci } 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci adapter->hw_tcs = 0; 11958c2ecf20Sopenharmony_ci adapter->dcb_cfg.num_tcs.pg_tcs = 1; 11968c2ecf20Sopenharmony_ci adapter->dcb_cfg.num_tcs.pfc_tcs = 1; 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci /* Disable SR-IOV support */ 11998c2ecf20Sopenharmony_ci e_dev_warn("Disabling SR-IOV support\n"); 12008c2ecf20Sopenharmony_ci ixgbe_disable_sriov(adapter); 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci /* Disable RSS */ 12038c2ecf20Sopenharmony_ci e_dev_warn("Disabling RSS support\n"); 12048c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_RSS].limit = 1; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci /* recalculate number of queues now that many features have been 12078c2ecf20Sopenharmony_ci * changed or disabled. 12088c2ecf20Sopenharmony_ci */ 12098c2ecf20Sopenharmony_ci ixgbe_set_num_queues(adapter); 12108c2ecf20Sopenharmony_ci adapter->num_q_vectors = 1; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci err = pci_enable_msi(adapter->pdev); 12138c2ecf20Sopenharmony_ci if (err) 12148c2ecf20Sopenharmony_ci e_dev_warn("Failed to allocate MSI interrupt, falling back to legacy. Error: %d\n", 12158c2ecf20Sopenharmony_ci err); 12168c2ecf20Sopenharmony_ci else 12178c2ecf20Sopenharmony_ci adapter->flags |= IXGBE_FLAG_MSI_ENABLED; 12188c2ecf20Sopenharmony_ci} 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci/** 12218c2ecf20Sopenharmony_ci * ixgbe_init_interrupt_scheme - Determine proper interrupt scheme 12228c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 12238c2ecf20Sopenharmony_ci * 12248c2ecf20Sopenharmony_ci * We determine which interrupt scheme to use based on... 12258c2ecf20Sopenharmony_ci * - Kernel support (MSI, MSI-X) 12268c2ecf20Sopenharmony_ci * - which can be user-defined (via MODULE_PARAM) 12278c2ecf20Sopenharmony_ci * - Hardware queue count (num_*_queues) 12288c2ecf20Sopenharmony_ci * - defined by miscellaneous hardware support/features (RSS, etc.) 12298c2ecf20Sopenharmony_ci **/ 12308c2ecf20Sopenharmony_ciint ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) 12318c2ecf20Sopenharmony_ci{ 12328c2ecf20Sopenharmony_ci int err; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci /* Number of supported queues */ 12358c2ecf20Sopenharmony_ci ixgbe_set_num_queues(adapter); 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci /* Set interrupt mode */ 12388c2ecf20Sopenharmony_ci ixgbe_set_interrupt_capability(adapter); 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci err = ixgbe_alloc_q_vectors(adapter); 12418c2ecf20Sopenharmony_ci if (err) { 12428c2ecf20Sopenharmony_ci e_dev_err("Unable to allocate memory for queue vectors\n"); 12438c2ecf20Sopenharmony_ci goto err_alloc_q_vectors; 12448c2ecf20Sopenharmony_ci } 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci ixgbe_cache_ring_register(adapter); 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci e_dev_info("Multiqueue %s: Rx Queue count = %u, Tx Queue count = %u XDP Queue count = %u\n", 12498c2ecf20Sopenharmony_ci (adapter->num_rx_queues > 1) ? "Enabled" : "Disabled", 12508c2ecf20Sopenharmony_ci adapter->num_rx_queues, adapter->num_tx_queues, 12518c2ecf20Sopenharmony_ci adapter->num_xdp_queues); 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci set_bit(__IXGBE_DOWN, &adapter->state); 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci return 0; 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_cierr_alloc_q_vectors: 12588c2ecf20Sopenharmony_ci ixgbe_reset_interrupt_capability(adapter); 12598c2ecf20Sopenharmony_ci return err; 12608c2ecf20Sopenharmony_ci} 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci/** 12638c2ecf20Sopenharmony_ci * ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings 12648c2ecf20Sopenharmony_ci * @adapter: board private structure to clear interrupt scheme on 12658c2ecf20Sopenharmony_ci * 12668c2ecf20Sopenharmony_ci * We go through and clear interrupt specific resources and reset the structure 12678c2ecf20Sopenharmony_ci * to pre-load conditions 12688c2ecf20Sopenharmony_ci **/ 12698c2ecf20Sopenharmony_civoid ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter) 12708c2ecf20Sopenharmony_ci{ 12718c2ecf20Sopenharmony_ci adapter->num_tx_queues = 0; 12728c2ecf20Sopenharmony_ci adapter->num_xdp_queues = 0; 12738c2ecf20Sopenharmony_ci adapter->num_rx_queues = 0; 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci ixgbe_free_q_vectors(adapter); 12768c2ecf20Sopenharmony_ci ixgbe_reset_interrupt_capability(adapter); 12778c2ecf20Sopenharmony_ci} 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_civoid ixgbe_tx_ctxtdesc(struct ixgbe_ring *tx_ring, u32 vlan_macip_lens, 12808c2ecf20Sopenharmony_ci u32 fceof_saidx, u32 type_tucmd, u32 mss_l4len_idx) 12818c2ecf20Sopenharmony_ci{ 12828c2ecf20Sopenharmony_ci struct ixgbe_adv_tx_context_desc *context_desc; 12838c2ecf20Sopenharmony_ci u16 i = tx_ring->next_to_use; 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci context_desc = IXGBE_TX_CTXTDESC(tx_ring, i); 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci i++; 12888c2ecf20Sopenharmony_ci tx_ring->next_to_use = (i < tx_ring->count) ? i : 0; 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci /* set bits to identify this as an advanced context descriptor */ 12918c2ecf20Sopenharmony_ci type_tucmd |= IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT; 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); 12948c2ecf20Sopenharmony_ci context_desc->fceof_saidx = cpu_to_le32(fceof_saidx); 12958c2ecf20Sopenharmony_ci context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); 12968c2ecf20Sopenharmony_ci context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); 12978c2ecf20Sopenharmony_ci} 12988c2ecf20Sopenharmony_ci 1299