Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue

Tony Nguyen says:

====================
This series contains updates to ice driver only.

Przemyslaw fixes memory leak of DMA memory due to incorrect freeing of
rx_buf.

Michal S corrects incorrect call to free memory.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2022-09-03 10:44:01 +01:00
commit cf5c15d1e9
4 changed files with 80 additions and 18 deletions

View File

@ -7,18 +7,6 @@
#include "ice_dcb_lib.h" #include "ice_dcb_lib.h"
#include "ice_sriov.h" #include "ice_sriov.h"
static bool ice_alloc_rx_buf_zc(struct ice_rx_ring *rx_ring)
{
rx_ring->xdp_buf = kcalloc(rx_ring->count, sizeof(*rx_ring->xdp_buf), GFP_KERNEL);
return !!rx_ring->xdp_buf;
}
static bool ice_alloc_rx_buf(struct ice_rx_ring *rx_ring)
{
rx_ring->rx_buf = kcalloc(rx_ring->count, sizeof(*rx_ring->rx_buf), GFP_KERNEL);
return !!rx_ring->rx_buf;
}
/** /**
* __ice_vsi_get_qs_contig - Assign a contiguous chunk of queues to VSI * __ice_vsi_get_qs_contig - Assign a contiguous chunk of queues to VSI
* @qs_cfg: gathered variables needed for PF->VSI queues assignment * @qs_cfg: gathered variables needed for PF->VSI queues assignment
@ -519,11 +507,8 @@ int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev, xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
ring->q_index, ring->q_vector->napi.napi_id); ring->q_index, ring->q_vector->napi.napi_id);
kfree(ring->rx_buf);
ring->xsk_pool = ice_xsk_pool(ring); ring->xsk_pool = ice_xsk_pool(ring);
if (ring->xsk_pool) { if (ring->xsk_pool) {
if (!ice_alloc_rx_buf_zc(ring))
return -ENOMEM;
xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq); xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq);
ring->rx_buf_len = ring->rx_buf_len =
@ -538,8 +523,6 @@ int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
dev_info(dev, "Registered XDP mem model MEM_TYPE_XSK_BUFF_POOL on Rx ring %d\n", dev_info(dev, "Registered XDP mem model MEM_TYPE_XSK_BUFF_POOL on Rx ring %d\n",
ring->q_index); ring->q_index);
} else { } else {
if (!ice_alloc_rx_buf(ring))
return -ENOMEM;
if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) if (!xdp_rxq_info_is_reg(&ring->xdp_rxq))
/* coverity[check_return] */ /* coverity[check_return] */
xdp_rxq_info_reg(&ring->xdp_rxq, xdp_rxq_info_reg(&ring->xdp_rxq,

View File

@ -2898,10 +2898,18 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
if (xdp_ring_err) if (xdp_ring_err)
NL_SET_ERR_MSG_MOD(extack, "Setting up XDP Tx resources failed"); NL_SET_ERR_MSG_MOD(extack, "Setting up XDP Tx resources failed");
} }
/* reallocate Rx queues that are used for zero-copy */
xdp_ring_err = ice_realloc_zc_buf(vsi, true);
if (xdp_ring_err)
NL_SET_ERR_MSG_MOD(extack, "Setting up XDP Rx resources failed");
} else if (ice_is_xdp_ena_vsi(vsi) && !prog) { } else if (ice_is_xdp_ena_vsi(vsi) && !prog) {
xdp_ring_err = ice_destroy_xdp_rings(vsi); xdp_ring_err = ice_destroy_xdp_rings(vsi);
if (xdp_ring_err) if (xdp_ring_err)
NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Tx resources failed"); NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Tx resources failed");
/* reallocate Rx queues that were used for zero-copy */
xdp_ring_err = ice_realloc_zc_buf(vsi, false);
if (xdp_ring_err)
NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Rx resources failed");
} else { } else {
/* safe to call even when prog == vsi->xdp_prog as /* safe to call even when prog == vsi->xdp_prog as
* dev_xdp_install in net/core/dev.c incremented prog's * dev_xdp_install in net/core/dev.c incremented prog's
@ -3905,7 +3913,7 @@ static int ice_init_pf(struct ice_pf *pf)
pf->avail_rxqs = bitmap_zalloc(pf->max_pf_rxqs, GFP_KERNEL); pf->avail_rxqs = bitmap_zalloc(pf->max_pf_rxqs, GFP_KERNEL);
if (!pf->avail_rxqs) { if (!pf->avail_rxqs) {
devm_kfree(ice_pf_to_dev(pf), pf->avail_txqs); bitmap_free(pf->avail_txqs);
pf->avail_txqs = NULL; pf->avail_txqs = NULL;
return -ENOMEM; return -ENOMEM;
} }

View File

@ -192,6 +192,7 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx)
err = ice_vsi_ctrl_one_rx_ring(vsi, false, q_idx, true); err = ice_vsi_ctrl_one_rx_ring(vsi, false, q_idx, true);
if (err) if (err)
return err; return err;
ice_clean_rx_ring(rx_ring);
ice_qvec_toggle_napi(vsi, q_vector, false); ice_qvec_toggle_napi(vsi, q_vector, false);
ice_qp_clean_rings(vsi, q_idx); ice_qp_clean_rings(vsi, q_idx);
@ -316,6 +317,62 @@ ice_xsk_pool_enable(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid)
return 0; return 0;
} }
/**
* ice_realloc_rx_xdp_bufs - reallocate for either XSK or normal buffer
* @rx_ring: 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
ice_realloc_rx_xdp_bufs(struct ice_rx_ring *rx_ring, bool pool_present)
{
size_t elem_size = pool_present ? sizeof(*rx_ring->xdp_buf) :
sizeof(*rx_ring->rx_buf);
void *sw_ring = kcalloc(rx_ring->count, elem_size, GFP_KERNEL);
if (!sw_ring)
return -ENOMEM;
if (pool_present) {
kfree(rx_ring->rx_buf);
rx_ring->rx_buf = NULL;
rx_ring->xdp_buf = sw_ring;
} else {
kfree(rx_ring->xdp_buf);
rx_ring->xdp_buf = NULL;
rx_ring->rx_buf = sw_ring;
}
return 0;
}
/**
* ice_realloc_zc_buf - reallocate XDP ZC 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 ice_realloc_zc_buf(struct ice_vsi *vsi, bool zc)
{
struct ice_rx_ring *rx_ring;
unsigned long q;
for_each_set_bit(q, vsi->af_xdp_zc_qps,
max_t(int, vsi->alloc_txq, vsi->alloc_rxq)) {
rx_ring = vsi->rx_rings[q];
if (ice_realloc_rx_xdp_bufs(rx_ring, zc))
return -ENOMEM;
}
return 0;
}
/** /**
* ice_xsk_pool_setup - enable/disable a buffer pool region depending on its state * ice_xsk_pool_setup - enable/disable a buffer pool region depending on its state
* @vsi: Current VSI * @vsi: Current VSI
@ -345,11 +402,17 @@ int ice_xsk_pool_setup(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid)
if_running = netif_running(vsi->netdev) && ice_is_xdp_ena_vsi(vsi); if_running = netif_running(vsi->netdev) && ice_is_xdp_ena_vsi(vsi);
if (if_running) { if (if_running) {
struct ice_rx_ring *rx_ring = vsi->rx_rings[qid];
ret = ice_qp_dis(vsi, qid); ret = ice_qp_dis(vsi, qid);
if (ret) { if (ret) {
netdev_err(vsi->netdev, "ice_qp_dis error = %d\n", ret); netdev_err(vsi->netdev, "ice_qp_dis error = %d\n", ret);
goto xsk_pool_if_up; goto xsk_pool_if_up;
} }
ret = ice_realloc_rx_xdp_bufs(rx_ring, pool_present);
if (ret)
goto xsk_pool_if_up;
} }
pool_failure = pool_present ? ice_xsk_pool_enable(vsi, pool, qid) : pool_failure = pool_present ? ice_xsk_pool_enable(vsi, pool, qid) :

View File

@ -27,6 +27,7 @@ bool ice_xsk_any_rx_ring_ena(struct ice_vsi *vsi);
void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring); void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring);
void ice_xsk_clean_xdp_ring(struct ice_tx_ring *xdp_ring); void ice_xsk_clean_xdp_ring(struct ice_tx_ring *xdp_ring);
bool ice_xmit_zc(struct ice_tx_ring *xdp_ring, u32 budget, int napi_budget); bool ice_xmit_zc(struct ice_tx_ring *xdp_ring, u32 budget, int napi_budget);
int ice_realloc_zc_buf(struct ice_vsi *vsi, bool zc);
#else #else
static inline bool static inline bool
ice_xmit_zc(struct ice_tx_ring __always_unused *xdp_ring, ice_xmit_zc(struct ice_tx_ring __always_unused *xdp_ring,
@ -72,5 +73,12 @@ ice_xsk_wakeup(struct net_device __always_unused *netdev,
static inline void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring) { } static inline void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring) { }
static inline void ice_xsk_clean_xdp_ring(struct ice_tx_ring *xdp_ring) { } static inline void ice_xsk_clean_xdp_ring(struct ice_tx_ring *xdp_ring) { }
static inline int
ice_realloc_zc_buf(struct ice_vsi __always_unused *vsi,
bool __always_unused zc)
{
return 0;
}
#endif /* CONFIG_XDP_SOCKETS */ #endif /* CONFIG_XDP_SOCKETS */
#endif /* !_ICE_XSK_H_ */ #endif /* !_ICE_XSK_H_ */