Commit cf5c15d1 authored by David S. Miller's avatar David S. Miller
Browse files


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: default avatarDavid S. Miller <davem@davemloft.net>
parents 3015c503 59ac3255
Loading
Loading
Loading
Loading
+0 −17
Original line number Diff line number Diff line
@@ -7,18 +7,6 @@
#include "ice_dcb_lib.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
 * @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,
					 ring->q_index, ring->q_vector->napi.napi_id);

		kfree(ring->rx_buf);
		ring->xsk_pool = ice_xsk_pool(ring);
		if (ring->xsk_pool) {
			if (!ice_alloc_rx_buf_zc(ring))
				return -ENOMEM;
			xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq);

			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",
				 ring->q_index);
		} else {
			if (!ice_alloc_rx_buf(ring))
				return -ENOMEM;
			if (!xdp_rxq_info_is_reg(&ring->xdp_rxq))
				/* coverity[check_return] */
				xdp_rxq_info_reg(&ring->xdp_rxq,
+9 −1
Original line number Diff line number Diff line
@@ -2898,10 +2898,18 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
			if (xdp_ring_err)
				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) {
		xdp_ring_err = ice_destroy_xdp_rings(vsi);
		if (xdp_ring_err)
			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 {
		/* safe to call even when prog == vsi->xdp_prog as
		 * 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);
	if (!pf->avail_rxqs) {
		devm_kfree(ice_pf_to_dev(pf), pf->avail_txqs);
		bitmap_free(pf->avail_txqs);
		pf->avail_txqs = NULL;
		return -ENOMEM;
	}
+63 −0
Original line number Diff line number Diff line
@@ -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);
	if (err)
		return err;
	ice_clean_rx_ring(rx_ring);

	ice_qvec_toggle_napi(vsi, q_vector, false);
	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;
}

/**
 * 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
 * @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 (if_running) {
		struct ice_rx_ring *rx_ring = vsi->rx_rings[qid];

		ret = ice_qp_dis(vsi, qid);
		if (ret) {
			netdev_err(vsi->netdev, "ice_qp_dis error = %d\n", ret);
			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) :
+8 −0
Original line number Diff line number Diff line
@@ -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_xdp_ring(struct ice_tx_ring *xdp_ring);
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
static inline bool
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_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 /* !_ICE_XSK_H_ */