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:
commit
cf5c15d1e9
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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) :
|
||||||
|
@ -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_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user