* [PATCH net v2 0/2][pull request] Intel Wired LAN Driver Updates 2022-09-28 (i40e) @ 2022-09-28 20:21 Tony Nguyen 2022-09-28 20:21 ` [PATCH net v2 1/2] i40e: Fix ethtool rx-flow-hash setting for X722 Tony Nguyen 2022-09-28 20:21 ` [PATCH net v2 2/2] i40e: Fix DMA mappings leak Tony Nguyen 0 siblings, 2 replies; 4+ messages in thread From: Tony Nguyen @ 2022-09-28 20:21 UTC (permalink / raw) To: davem, kuba, pabeni, edumazet; +Cc: Tony Nguyen, netdev This series contains updates to i40e driver only. Slawomir fixes using incorrect register masks on X722 devices. Jan fixes memory leak of DMA memory due to incorrect freeing of rx_buf. --- v2: Drop XPS patch, previously patch 2. The following are changes since commit 44d70bb561dac9363f45787aa93dfca36877ee01: Merge tag 'wireless-2022-09-27' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless and are available in the git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue 40GbE Jan Sokolowski (1): i40e: Fix DMA mappings leak Slawomir Laba (1): i40e: Fix ethtool rx-flow-hash setting for X722 .../net/ethernet/intel/i40e/i40e_ethtool.c | 34 +++++++--- drivers/net/ethernet/intel/i40e/i40e_main.c | 13 ++-- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 13 ++-- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 - drivers/net/ethernet/intel/i40e/i40e_type.h | 4 ++ drivers/net/ethernet/intel/i40e/i40e_xsk.c | 67 ++++++++++++++++--- drivers/net/ethernet/intel/i40e/i40e_xsk.h | 2 +- 7 files changed, 98 insertions(+), 36 deletions(-) -- 2.35.1 ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH net v2 1/2] i40e: Fix ethtool rx-flow-hash setting for X722 2022-09-28 20:21 [PATCH net v2 0/2][pull request] Intel Wired LAN Driver Updates 2022-09-28 (i40e) Tony Nguyen @ 2022-09-28 20:21 ` Tony Nguyen 2022-09-28 20:21 ` [PATCH net v2 2/2] i40e: Fix DMA mappings leak Tony Nguyen 1 sibling, 0 replies; 4+ messages in thread From: Tony Nguyen @ 2022-09-28 20:21 UTC (permalink / raw) To: davem, kuba, pabeni, edumazet Cc: Slawomir Laba, netdev, anthony.l.nguyen, Michal Jaron, Mateusz Palczewski, Gurucharan From: Slawomir Laba <slawomirx.laba@intel.com> When enabling flow type for RSS hash via ethtool: ethtool -N $pf rx-flow-hash tcp4|tcp6|udp4|udp6 s|d the driver would fail to setup this setting on X722 device since it was using the mask on the register dedicated for X710 devices. Apply a different mask on the register when setting the RSS hash for the X722 device. When displaying the flow types enabled via ethtool: ethtool -n $pf rx-flow-hash tcp4|tcp6|udp4|udp6 the driver would print wrong values for X722 device. Fix this issue by testing masks for X722 device in i40e_get_rss_hash_opts function. Fixes: eb0dd6e4a3b3 ("i40e: Allow RSS Hash set with less than four parameters") Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com> Signed-off-by: Michal Jaron <michalx.jaron@intel.com> Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com> Tested-by: Gurucharan <gurucharanx.g@intel.com> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> --- .../net/ethernet/intel/i40e/i40e_ethtool.c | 31 ++++++++++++++----- drivers/net/ethernet/intel/i40e/i40e_type.h | 4 +++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index e9cd0fa6a0d2..e518aaa2c0ca 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -3188,10 +3188,17 @@ static int i40e_get_rss_hash_opts(struct i40e_pf *pf, struct ethtool_rxnfc *cmd) if (cmd->flow_type == TCP_V4_FLOW || cmd->flow_type == UDP_V4_FLOW) { - if (i_set & I40E_L3_SRC_MASK) - cmd->data |= RXH_IP_SRC; - if (i_set & I40E_L3_DST_MASK) - cmd->data |= RXH_IP_DST; + if (hw->mac.type == I40E_MAC_X722) { + if (i_set & I40E_X722_L3_SRC_MASK) + cmd->data |= RXH_IP_SRC; + if (i_set & I40E_X722_L3_DST_MASK) + cmd->data |= RXH_IP_DST; + } else { + if (i_set & I40E_L3_SRC_MASK) + cmd->data |= RXH_IP_SRC; + if (i_set & I40E_L3_DST_MASK) + cmd->data |= RXH_IP_DST; + } } else if (cmd->flow_type == TCP_V6_FLOW || cmd->flow_type == UDP_V6_FLOW) { if (i_set & I40E_L3_V6_SRC_MASK) @@ -3549,12 +3556,15 @@ static int i40e_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, /** * i40e_get_rss_hash_bits - Read RSS Hash bits from register + * @hw: hw structure * @nfc: pointer to user request * @i_setc: bits currently set * * Returns value of bits to be set per user request **/ -static u64 i40e_get_rss_hash_bits(struct ethtool_rxnfc *nfc, u64 i_setc) +static u64 i40e_get_rss_hash_bits(struct i40e_hw *hw, + struct ethtool_rxnfc *nfc, + u64 i_setc) { u64 i_set = i_setc; u64 src_l3 = 0, dst_l3 = 0; @@ -3573,8 +3583,13 @@ static u64 i40e_get_rss_hash_bits(struct ethtool_rxnfc *nfc, u64 i_setc) dst_l3 = I40E_L3_V6_DST_MASK; } else if (nfc->flow_type == TCP_V4_FLOW || nfc->flow_type == UDP_V4_FLOW) { - src_l3 = I40E_L3_SRC_MASK; - dst_l3 = I40E_L3_DST_MASK; + if (hw->mac.type == I40E_MAC_X722) { + src_l3 = I40E_X722_L3_SRC_MASK; + dst_l3 = I40E_X722_L3_DST_MASK; + } else { + src_l3 = I40E_L3_SRC_MASK; + dst_l3 = I40E_L3_DST_MASK; + } } else { /* Any other flow type are not supported here */ return i_set; @@ -3689,7 +3704,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) flow_pctype)) | ((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_pctype)) << 32); - i_set = i40e_get_rss_hash_bits(nfc, i_setc); + i_set = i40e_get_rss_hash_bits(&pf->hw, nfc, i_setc); i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_pctype), (u32)i_set); i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_pctype), diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 7b3f30beb757..388c3d36d96a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -1404,6 +1404,10 @@ struct i40e_lldp_variables { #define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000 /* INPUT SET MASK for RSS, flow director, and flexible payload */ +#define I40E_X722_L3_SRC_SHIFT 49 +#define I40E_X722_L3_SRC_MASK (0x3ULL << I40E_X722_L3_SRC_SHIFT) +#define I40E_X722_L3_DST_SHIFT 41 +#define I40E_X722_L3_DST_MASK (0x3ULL << I40E_X722_L3_DST_SHIFT) #define I40E_L3_SRC_SHIFT 47 #define I40E_L3_SRC_MASK (0x3ULL << I40E_L3_SRC_SHIFT) #define I40E_L3_V6_SRC_SHIFT 43 -- 2.35.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH net v2 2/2] i40e: Fix DMA mappings leak 2022-09-28 20:21 [PATCH net v2 0/2][pull request] Intel Wired LAN Driver Updates 2022-09-28 (i40e) Tony Nguyen 2022-09-28 20:21 ` [PATCH net v2 1/2] i40e: Fix ethtool rx-flow-hash setting for X722 Tony Nguyen @ 2022-09-28 20:21 ` Tony Nguyen 2022-09-29 11:12 ` Maciej Fijalkowski 1 sibling, 1 reply; 4+ messages in thread From: Tony Nguyen @ 2022-09-28 20:21 UTC (permalink / raw) To: davem, kuba, pabeni, edumazet Cc: Jan Sokolowski, netdev, anthony.l.nguyen, bjorn, maciej.fijalkowski, magnus.karlsson, ast, daniel, hawk, john.fastabend, bpf, Chandan From: Jan Sokolowski <jan.sokolowski@intel.com> During reallocation of RX buffers, new DMA mappings are created for those buffers. New buffers with different RX ring count should substitute older ones, but those buffers were freed in i40e_configure_rx_ring and reallocated again with i40e_alloc_rx_bi, thus kfree on rx_bi caused leak of already mapped DMA. In case of non XDP ring, do not free rx_bi and reuse already existing buffer, move kfree to XDP rings only, remove unused i40e_alloc_rx_bi function. steps for reproduction: while : do for ((i=0; i<=8160; i=i+32)) do ethtool -G enp130s0f0 rx $i tx $i sleep 0.5 ethtool -g enp130s0f0 done done Fixes: be1222b585fd ("i40e: Separate kernel allocated rx_bi rings from AF_XDP rings") Signed-off-by: Jan Sokolowski <jan.sokolowski@intel.com> Tested-by: Chandan <chandanx.rout@intel.com> (A Contingent Worker at Intel) Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> --- .../net/ethernet/intel/i40e/i40e_ethtool.c | 3 - drivers/net/ethernet/intel/i40e/i40e_main.c | 13 ++-- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 13 ++-- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 - drivers/net/ethernet/intel/i40e/i40e_xsk.c | 67 ++++++++++++++++--- drivers/net/ethernet/intel/i40e/i40e_xsk.h | 2 +- 6 files changed, 71 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index e518aaa2c0ca..0f2042f1597c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -2181,9 +2181,6 @@ static int i40e_set_ringparam(struct net_device *netdev, */ rx_rings[i].tail = hw->hw_addr + I40E_PRTGEN_STATUS; err = i40e_setup_rx_descriptors(&rx_rings[i]); - if (err) - goto rx_unwind; - err = i40e_alloc_rx_bi(&rx_rings[i]); if (err) goto rx_unwind; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index e3d9804aeb25..ad15749a2dd3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3565,12 +3565,8 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring) if (ring->vsi->type == I40E_VSI_MAIN) xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq); - kfree(ring->rx_bi); ring->xsk_pool = i40e_xsk_pool(ring); if (ring->xsk_pool) { - ret = i40e_alloc_rx_bi_zc(ring); - if (ret) - return ret; ring->rx_buf_len = xsk_pool_get_rx_frame_size(ring->xsk_pool); /* For AF_XDP ZC, we disallow packets to span on @@ -3588,9 +3584,6 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring) ring->queue_index); } else { - ret = i40e_alloc_rx_bi(ring); - if (ret) - return ret; ring->rx_buf_len = vsi->rx_buf_len; if (ring->vsi->type == I40E_VSI_MAIN) { ret = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, @@ -13304,6 +13297,11 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog, i40e_reset_and_rebuild(pf, true, true); } + if (!i40e_enabled_xdp_vsi(vsi) && prog) + i40e_realloc_rx_bi_zc(vsi, true); + else if (i40e_enabled_xdp_vsi(vsi) && !prog) + i40e_realloc_rx_bi_zc(vsi, false); + for (i = 0; i < vsi->num_queue_pairs; i++) WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog); @@ -13536,6 +13534,7 @@ int i40e_queue_pair_disable(struct i40e_vsi *vsi, int queue_pair) i40e_queue_pair_disable_irq(vsi, queue_pair); err = i40e_queue_pair_toggle_rings(vsi, queue_pair, false /* off */); + i40e_clean_rx_ring(vsi->rx_rings[queue_pair]); i40e_queue_pair_toggle_napi(vsi, queue_pair, false /* off */); i40e_queue_pair_clean_rings(vsi, queue_pair); i40e_queue_pair_reset_stats(vsi, queue_pair); diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 69e67eb6aea7..b97c95f89fa0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1457,14 +1457,6 @@ int i40e_setup_tx_descriptors(struct i40e_ring *tx_ring) return -ENOMEM; } -int i40e_alloc_rx_bi(struct i40e_ring *rx_ring) -{ - unsigned long sz = sizeof(*rx_ring->rx_bi) * rx_ring->count; - - rx_ring->rx_bi = kzalloc(sz, GFP_KERNEL); - return rx_ring->rx_bi ? 0 : -ENOMEM; -} - static void i40e_clear_rx_bi(struct i40e_ring *rx_ring) { memset(rx_ring->rx_bi, 0, sizeof(*rx_ring->rx_bi) * rx_ring->count); @@ -1593,6 +1585,11 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring) rx_ring->xdp_prog = rx_ring->vsi->xdp_prog; + rx_ring->rx_bi = + kcalloc(rx_ring->count, sizeof(*rx_ring->rx_bi), GFP_KERNEL); + if (!rx_ring->rx_bi) + return -ENOMEM; + return 0; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 41f86e9535a0..768290dc6f48 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -469,7 +469,6 @@ int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size); bool __i40e_chk_linearize(struct sk_buff *skb); int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, u32 flags); -int i40e_alloc_rx_bi(struct i40e_ring *rx_ring); /** * i40e_get_head - Retrieve head from head writeback diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index 6d4009e0cbd6..790aaeff1b47 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -10,14 +10,6 @@ #include "i40e_txrx_common.h" #include "i40e_xsk.h" -int i40e_alloc_rx_bi_zc(struct i40e_ring *rx_ring) -{ - unsigned long sz = sizeof(*rx_ring->rx_bi_zc) * rx_ring->count; - - rx_ring->rx_bi_zc = kzalloc(sz, GFP_KERNEL); - return rx_ring->rx_bi_zc ? 0 : -ENOMEM; -} - void i40e_clear_rx_bi_zc(struct i40e_ring *rx_ring) { memset(rx_ring->rx_bi_zc, 0, @@ -29,6 +21,58 @@ static struct xdp_buff **i40e_rx_bi(struct i40e_ring *rx_ring, u32 idx) return &rx_ring->rx_bi_zc[idx]; } +/** + * i40e_realloc_rx_xdp_bi - reallocate for either XSK or normal buffer + * @rx_ring: Current rx ring + * @pool_present: is pool for XSK present + * + * Try allocating memory and return ENOMEM, if failed to allocate. + * If allocation was successful, substitute buffer with allocated one. + * Returns 0 on success, negative on failure + */ +static int i40e_realloc_rx_xdp_bi(struct i40e_ring *rx_ring, bool pool_present) +{ + size_t elem_size = pool_present ? sizeof(*rx_ring->rx_bi_zc) : + sizeof(*rx_ring->rx_bi); + void *sw_ring = kcalloc(rx_ring->count, elem_size, GFP_KERNEL); + + if (!sw_ring) + return -ENOMEM; + + if (pool_present) { + kfree(rx_ring->rx_bi); + rx_ring->rx_bi = NULL; + rx_ring->rx_bi_zc = sw_ring; + } else { + kfree(rx_ring->rx_bi_zc); + rx_ring->rx_bi_zc = NULL; + rx_ring->rx_bi = sw_ring; + } + return 0; +} + +/** + * i40e_realloc_rx_bi_zc - reallocate xdp queue pairs + * @vsi: Current VSI + * @zc: is zero copy set + * + * Reallocate buffer for rx_rings that might be used by XSK. + * XDP requires more memory, than rx_buf provides. + * Returns 0 on success, negative on failure + */ +int i40e_realloc_rx_bi_zc(struct i40e_vsi *vsi, bool zc) +{ + struct i40e_ring *rx_ring; + unsigned long q; + + for_each_set_bit(q, vsi->af_xdp_zc_qps, vsi->alloc_queue_pairs) { + rx_ring = vsi->rx_rings[q]; + if (i40e_realloc_rx_xdp_bi(rx_ring, zc)) + return -ENOMEM; + } + return 0; +} + /** * i40e_xsk_pool_enable - Enable/associate an AF_XDP buffer pool to a * certain ring/qid @@ -69,6 +113,10 @@ static int i40e_xsk_pool_enable(struct i40e_vsi *vsi, if (err) return err; + err = i40e_realloc_rx_xdp_bi(vsi->rx_rings[qid], true); + if (err) + return err; + err = i40e_queue_pair_enable(vsi, qid); if (err) return err; @@ -113,6 +161,9 @@ static int i40e_xsk_pool_disable(struct i40e_vsi *vsi, u16 qid) xsk_pool_dma_unmap(pool, I40E_RX_DMA_ATTR); if (if_running) { + err = i40e_realloc_rx_xdp_bi(vsi->rx_rings[qid], false); + if (err) + return err; err = i40e_queue_pair_enable(vsi, qid); if (err) return err; diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.h b/drivers/net/ethernet/intel/i40e/i40e_xsk.h index bb962987f300..821df248f8be 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.h +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.h @@ -32,7 +32,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget); bool i40e_clean_xdp_tx_irq(struct i40e_vsi *vsi, struct i40e_ring *tx_ring); int i40e_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags); -int i40e_alloc_rx_bi_zc(struct i40e_ring *rx_ring); +int i40e_realloc_rx_bi_zc(struct i40e_vsi *vsi, bool zc); void i40e_clear_rx_bi_zc(struct i40e_ring *rx_ring); #endif /* _I40E_XSK_H_ */ -- 2.35.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH net v2 2/2] i40e: Fix DMA mappings leak 2022-09-28 20:21 ` [PATCH net v2 2/2] i40e: Fix DMA mappings leak Tony Nguyen @ 2022-09-29 11:12 ` Maciej Fijalkowski 0 siblings, 0 replies; 4+ messages in thread From: Maciej Fijalkowski @ 2022-09-29 11:12 UTC (permalink / raw) To: Tony Nguyen Cc: davem, kuba, pabeni, edumazet, Jan Sokolowski, netdev, bjorn, magnus.karlsson, ast, daniel, hawk, john.fastabend, bpf, Chandan On Wed, Sep 28, 2022 at 01:21:38PM -0700, Tony Nguyen wrote: > From: Jan Sokolowski <jan.sokolowski@intel.com> Hi Jan, Tony, > > During reallocation of RX buffers, new DMA mappings are created for > those buffers. New buffers with different RX ring count should > substitute older ones, but those buffers were freed in > i40e_configure_rx_ring and reallocated again with i40e_alloc_rx_bi, > thus kfree on rx_bi caused leak of already mapped DMA. > > In case of non XDP ring, do not free rx_bi and reuse already existing Out of the sudden you talk about non XDP ring so I would expect some reference to XDP ring before that? TBH I was having a hard time reading the commit message from ice based patch and it was c&ped from there. For example, it says nothing about newly introduced i40e_realloc_rx_xdp_bi(), i40e_realloc_rx_bi_zc(). > buffer, move kfree to XDP rings only, remove unused i40e_alloc_rx_bi > function. > > steps for reproduction: > while : > do > for ((i=0; i<=8160; i=i+32)) > do > ethtool -G enp130s0f0 rx $i tx $i > sleep 0.5 > ethtool -g enp130s0f0 > done > done > > Fixes: be1222b585fd ("i40e: Separate kernel allocated rx_bi rings from AF_XDP rings") > Signed-off-by: Jan Sokolowski <jan.sokolowski@intel.com> > Tested-by: Chandan <chandanx.rout@intel.com> (A Contingent Worker at Intel) I looked through my inbox and it seems that you provide different names {Chandan, Chandan Rout, Chandan Kumar Rout} with your tested-by tag, why? > Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> > --- > .../net/ethernet/intel/i40e/i40e_ethtool.c | 3 - > drivers/net/ethernet/intel/i40e/i40e_main.c | 13 ++-- > drivers/net/ethernet/intel/i40e/i40e_txrx.c | 13 ++-- > drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 - > drivers/net/ethernet/intel/i40e/i40e_xsk.c | 67 ++++++++++++++++--- > drivers/net/ethernet/intel/i40e/i40e_xsk.h | 2 +- > 6 files changed, 71 insertions(+), 28 deletions(-) > > diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c > index e518aaa2c0ca..0f2042f1597c 100644 > --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c > +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c > @@ -2181,9 +2181,6 @@ static int i40e_set_ringparam(struct net_device *netdev, > */ > rx_rings[i].tail = hw->hw_addr + I40E_PRTGEN_STATUS; > err = i40e_setup_rx_descriptors(&rx_rings[i]); > - if (err) > - goto rx_unwind; > - err = i40e_alloc_rx_bi(&rx_rings[i]); > if (err) > goto rx_unwind; > > diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c > index e3d9804aeb25..ad15749a2dd3 100644 > --- a/drivers/net/ethernet/intel/i40e/i40e_main.c > +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c > @@ -3565,12 +3565,8 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring) > if (ring->vsi->type == I40E_VSI_MAIN) > xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq); > > - kfree(ring->rx_bi); > ring->xsk_pool = i40e_xsk_pool(ring); > if (ring->xsk_pool) { > - ret = i40e_alloc_rx_bi_zc(ring); > - if (ret) > - return ret; > ring->rx_buf_len = > xsk_pool_get_rx_frame_size(ring->xsk_pool); > /* For AF_XDP ZC, we disallow packets to span on > @@ -3588,9 +3584,6 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring) > ring->queue_index); > > } else { > - ret = i40e_alloc_rx_bi(ring); > - if (ret) > - return ret; > ring->rx_buf_len = vsi->rx_buf_len; > if (ring->vsi->type == I40E_VSI_MAIN) { > ret = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, > @@ -13304,6 +13297,11 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog, > i40e_reset_and_rebuild(pf, true, true); > } > > + if (!i40e_enabled_xdp_vsi(vsi) && prog) > + i40e_realloc_rx_bi_zc(vsi, true); > + else if (i40e_enabled_xdp_vsi(vsi) && !prog) > + i40e_realloc_rx_bi_zc(vsi, false); why retvals are ignored? Please explain this better in the commit message so that in future we will be able to refer to it and understand the reason why we're doing it in this way. > + > for (i = 0; i < vsi->num_queue_pairs; i++) > WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog); > > @@ -13536,6 +13534,7 @@ int i40e_queue_pair_disable(struct i40e_vsi *vsi, int queue_pair) > > i40e_queue_pair_disable_irq(vsi, queue_pair); > err = i40e_queue_pair_toggle_rings(vsi, queue_pair, false /* off */); > + i40e_clean_rx_ring(vsi->rx_rings[queue_pair]); > i40e_queue_pair_toggle_napi(vsi, queue_pair, false /* off */); > i40e_queue_pair_clean_rings(vsi, queue_pair); > i40e_queue_pair_reset_stats(vsi, queue_pair); > diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c > index 69e67eb6aea7..b97c95f89fa0 100644 > --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c > +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c > @@ -1457,14 +1457,6 @@ int i40e_setup_tx_descriptors(struct i40e_ring *tx_ring) > return -ENOMEM; > } > > -int i40e_alloc_rx_bi(struct i40e_ring *rx_ring) > -{ > - unsigned long sz = sizeof(*rx_ring->rx_bi) * rx_ring->count; > - > - rx_ring->rx_bi = kzalloc(sz, GFP_KERNEL); > - return rx_ring->rx_bi ? 0 : -ENOMEM; > -} > - > static void i40e_clear_rx_bi(struct i40e_ring *rx_ring) > { > memset(rx_ring->rx_bi, 0, sizeof(*rx_ring->rx_bi) * rx_ring->count); > @@ -1593,6 +1585,11 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring) > > rx_ring->xdp_prog = rx_ring->vsi->xdp_prog; > > + rx_ring->rx_bi = > + kcalloc(rx_ring->count, sizeof(*rx_ring->rx_bi), GFP_KERNEL); > + if (!rx_ring->rx_bi) > + return -ENOMEM; > + > return 0; > } > > diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h > index 41f86e9535a0..768290dc6f48 100644 > --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h > +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h > @@ -469,7 +469,6 @@ int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size); > bool __i40e_chk_linearize(struct sk_buff *skb); > int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, > u32 flags); > -int i40e_alloc_rx_bi(struct i40e_ring *rx_ring); > > /** > * i40e_get_head - Retrieve head from head writeback > diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c > index 6d4009e0cbd6..790aaeff1b47 100644 > --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c > +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c > @@ -10,14 +10,6 @@ > #include "i40e_txrx_common.h" > #include "i40e_xsk.h" > > -int i40e_alloc_rx_bi_zc(struct i40e_ring *rx_ring) > -{ > - unsigned long sz = sizeof(*rx_ring->rx_bi_zc) * rx_ring->count; > - > - rx_ring->rx_bi_zc = kzalloc(sz, GFP_KERNEL); > - return rx_ring->rx_bi_zc ? 0 : -ENOMEM; > -} > - > void i40e_clear_rx_bi_zc(struct i40e_ring *rx_ring) > { > memset(rx_ring->rx_bi_zc, 0, > @@ -29,6 +21,58 @@ static struct xdp_buff **i40e_rx_bi(struct i40e_ring *rx_ring, u32 idx) > return &rx_ring->rx_bi_zc[idx]; > } > > +/** > + * i40e_realloc_rx_xdp_bi - reallocate for either XSK or normal buffer reallocate SW ring > + * @rx_ring: Current rx ring > + * @pool_present: is pool for XSK present > + * > + * Try allocating memory and return ENOMEM, if failed to allocate. > + * If allocation was successful, substitute buffer with allocated one. > + * Returns 0 on success, negative on failure > + */ > +static int i40e_realloc_rx_xdp_bi(struct i40e_ring *rx_ring, bool pool_present) > +{ > + size_t elem_size = pool_present ? sizeof(*rx_ring->rx_bi_zc) : > + sizeof(*rx_ring->rx_bi); > + void *sw_ring = kcalloc(rx_ring->count, elem_size, GFP_KERNEL); > + > + if (!sw_ring) > + return -ENOMEM; > + > + if (pool_present) { > + kfree(rx_ring->rx_bi); > + rx_ring->rx_bi = NULL; > + rx_ring->rx_bi_zc = sw_ring; > + } else { > + kfree(rx_ring->rx_bi_zc); > + rx_ring->rx_bi_zc = NULL; > + rx_ring->rx_bi = sw_ring; > + } > + return 0; > +} > + > +/** > + * i40e_realloc_rx_bi_zc - reallocate xdp queue pairs queue pairs?? rather Rx SW rings? > + * @vsi: Current VSI > + * @zc: is zero copy set > + * > + * Reallocate buffer for rx_rings that might be used by XSK. > + * XDP requires more memory, than rx_buf provides. > + * Returns 0 on success, negative on failure > + */ > +int i40e_realloc_rx_bi_zc(struct i40e_vsi *vsi, bool zc) > +{ > + struct i40e_ring *rx_ring; > + unsigned long q; > + > + for_each_set_bit(q, vsi->af_xdp_zc_qps, vsi->alloc_queue_pairs) { > + rx_ring = vsi->rx_rings[q]; > + if (i40e_realloc_rx_xdp_bi(rx_ring, zc)) > + return -ENOMEM; > + } > + return 0; > +} > + > /** > * i40e_xsk_pool_enable - Enable/associate an AF_XDP buffer pool to a > * certain ring/qid > @@ -69,6 +113,10 @@ static int i40e_xsk_pool_enable(struct i40e_vsi *vsi, > if (err) > return err; > > + err = i40e_realloc_rx_xdp_bi(vsi->rx_rings[qid], true); > + if (err) > + return err; > + > err = i40e_queue_pair_enable(vsi, qid); > if (err) > return err; > @@ -113,6 +161,9 @@ static int i40e_xsk_pool_disable(struct i40e_vsi *vsi, u16 qid) > xsk_pool_dma_unmap(pool, I40E_RX_DMA_ATTR); > > if (if_running) { > + err = i40e_realloc_rx_xdp_bi(vsi->rx_rings[qid], false); > + if (err) > + return err; > err = i40e_queue_pair_enable(vsi, qid); > if (err) > return err; > diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.h b/drivers/net/ethernet/intel/i40e/i40e_xsk.h > index bb962987f300..821df248f8be 100644 > --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.h > +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.h > @@ -32,7 +32,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget); > > bool i40e_clean_xdp_tx_irq(struct i40e_vsi *vsi, struct i40e_ring *tx_ring); > int i40e_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags); > -int i40e_alloc_rx_bi_zc(struct i40e_ring *rx_ring); > +int i40e_realloc_rx_bi_zc(struct i40e_vsi *vsi, bool zc); > void i40e_clear_rx_bi_zc(struct i40e_ring *rx_ring); > > #endif /* _I40E_XSK_H_ */ > -- > 2.35.1 > ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-09-29 11:12 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-09-28 20:21 [PATCH net v2 0/2][pull request] Intel Wired LAN Driver Updates 2022-09-28 (i40e) Tony Nguyen 2022-09-28 20:21 ` [PATCH net v2 1/2] i40e: Fix ethtool rx-flow-hash setting for X722 Tony Nguyen 2022-09-28 20:21 ` [PATCH net v2 2/2] i40e: Fix DMA mappings leak Tony Nguyen 2022-09-29 11:12 ` Maciej Fijalkowski
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).