Commit 1c978616 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2024-11-05 (ice, ixgbe, igc. igb, igbvf, e1000)

For ice:

Mateusz refactors and adds additional SerDes configuration values to be
output.

Przemek refactors processing of DDP and adds support for a flag field in
the DDP's signature segment header.

Joe Damato adds support for persistent NAPI config.

Brett adjusts setting of Tx promiscuous based on unicast/multicast
setting.

Jake moves setting of pf->supported_rxdids to occur directly after DDP
load and changes a small struct to use stack memory.

Frederic Weisbecker adds WQ_UNBOUND flag to the workqueue.

For ixgbe:

Diomidis Spinellis removes a circular dependency.

For igc:

Vitaly removes an unneeded autoneg parameter.

For igb:

Johnny Park fixes a couple of typos.

For igbvf:

Wander Lairson Costa removes an unused spinlock.

For e1000:

Joe Damato adds RTNL lock to some calls where it is expected to be held.

* '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
  e1000: Hold RTNL when e1000_down can be called
  igbvf: remove unused spinlock
  igb: Fix 2 typos in comments in igb_main.c
  igc: remove autoneg parameter from igc_mac_info
  ixgbe: Break include dependency cycle
  ice: Unbind the workqueue
  ice: use stack variable for virtchnl_supported_rxdids
  ice: initialize pf->supported_rxdids immediately after loading DDP
  ice: only allow Tx promiscuous for multicast
  ice: Add support for persistent NAPI config
  ice: support optional flags in signature segment header
  ice: refactor "last" segment of DDP pkg
  ice: extend dump serdes equalizer values feature
  ice: rework of dump serdes equalizer values feature
====================

Link: https://patch.msgid.link/20241113185431.1289708-1-anthony.l.nguyen@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents e709d442 e400c744
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -3509,7 +3509,9 @@ static void e1000_reset_task(struct work_struct *work)
		container_of(work, struct e1000_adapter, reset_task);

	e_err(drv, "Reset adapter\n");
	rtnl_lock();
	e1000_reinit_locked(adapter);
	rtnl_unlock();
}

/**
@@ -5074,7 +5076,9 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
			usleep_range(10000, 20000);

		WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
		rtnl_lock();
		e1000_down(adapter);
		rtnl_unlock();
	}

	status = er32(STATUS);
@@ -5235,16 +5239,20 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
	struct net_device *netdev = pci_get_drvdata(pdev);
	struct e1000_adapter *adapter = netdev_priv(netdev);

	rtnl_lock();
	netif_device_detach(netdev);

	if (state == pci_channel_io_perm_failure)
	if (state == pci_channel_io_perm_failure) {
		rtnl_unlock();
		return PCI_ERS_RESULT_DISCONNECT;
	}

	if (netif_running(netdev))
		e1000_down(adapter);

	if (!test_and_set_bit(__E1000_DISABLED, &adapter->flags))
		pci_disable_device(pdev);
	rtnl_unlock();

	/* Request a slot reset. */
	return PCI_ERS_RESULT_NEED_RESET;
+2 −4
Original line number Diff line number Diff line
@@ -181,11 +181,9 @@
#define ice_for_each_chnl_tc(i)	\
	for ((i) = ICE_CHNL_START_TC; (i) < ICE_CHNL_MAX_TC; (i)++)

#define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_UCAST_RX)
#define ICE_UCAST_PROMISC_BITS ICE_PROMISC_UCAST_RX

#define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_TX | \
				     ICE_PROMISC_UCAST_RX | \
				     ICE_PROMISC_VLAN_TX  | \
#define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_RX | \
				     ICE_PROMISC_VLAN_RX)

#define ICE_MCAST_PROMISC_BITS (ICE_PROMISC_MCAST_TX | ICE_PROMISC_MCAST_RX)
+17 −0
Original line number Diff line number Diff line
@@ -1492,6 +1492,23 @@ struct ice_aqc_dnl_equa_param {
#define ICE_AQC_RX_EQU_BFLF (0x13 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_BFHF (0x14 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DRATE (0x15 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_CTLE_GAINHF (0x20 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_CTLE_GAINLF (0x21 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_CTLE_GAINDC (0x22 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_CTLE_BW (0x23 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_GAIN (0x30 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_GAIN2 (0x31 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_2 (0x32 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_3 (0x33 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_4 (0x34 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_5 (0x35 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_6 (0x36 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_7 (0x37 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_8 (0x38 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_9 (0x39 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_10 (0x3A << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_11 (0x3B << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DFE_12 (0x3C << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_TX_EQU_PRE1 0x0
#define ICE_AQC_TX_EQU_PRE3 0x3
#define ICE_AQC_TX_EQU_ATTEN 0x4
+2 −1
Original line number Diff line number Diff line
@@ -156,7 +156,8 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx)
	 * handler here (i.e. resume, reset/rebuild, etc.)
	 */
	if (vsi->netdev)
		netif_napi_add(vsi->netdev, &q_vector->napi, ice_napi_poll);
		netif_napi_add_config(vsi->netdev, &q_vector->napi,
				      ice_napi_poll, v_idx);

out:
	/* tie q_vector and VSI together */
+163 −139
Original line number Diff line number Diff line
@@ -1210,6 +1210,131 @@ ice_aq_download_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf,
	return status;
}

/**
 * ice_is_buffer_metadata - determine if package buffer is a metadata buffer
 * @buf: pointer to buffer header
 * Return: whether given @buf is a metadata one.
 */
static bool ice_is_buffer_metadata(struct ice_buf_hdr *buf)
{
	return le32_to_cpu(buf->section_entry[0].type) & ICE_METADATA_BUF;
}

/**
 * struct ice_ddp_send_ctx - sending context of current DDP segment
 * @hw: pointer to the hardware struct
 *
 * Keeps current sending state (header, error) for the purpose of proper "last"
 * bit setting in ice_aq_download_pkg(). Use via calls to ice_ddp_send_hunk().
 */
struct ice_ddp_send_ctx {
	struct ice_hw *hw;
/* private: only for ice_ddp_send_hunk() */
	struct ice_buf_hdr *hdr;
	int err;
};

static void ice_ddp_send_ctx_set_err(struct ice_ddp_send_ctx *ctx, int err)
{
	ctx->err = err;
}

/**
 * ice_ddp_send_hunk - send one hunk of data to FW
 * @ctx: current segment sending context
 * @hunk: next hunk to send, size is always ICE_PKG_BUF_SIZE
 *
 * Send the next hunk of data to FW, retrying if needed.
 *
 * Notice: must be called once more with a NULL @hunk to finish up; such call
 * will set up the "last" bit of an AQ request. After such call @ctx.hdr is
 * cleared, @hw is still valid.
 *
 * Return: %ICE_DDP_PKG_SUCCESS if there were no problems; a sticky @err
 *         otherwise.
 */
static enum ice_ddp_state ice_ddp_send_hunk(struct ice_ddp_send_ctx *ctx,
					    struct ice_buf_hdr *hunk)
{
	struct ice_buf_hdr *prev_hunk = ctx->hdr;
	struct ice_hw *hw = ctx->hw;
	bool prev_was_last = !hunk;
	enum ice_aq_err aq_err;
	u32 offset, info;
	int attempt, err;

	if (ctx->err)
		return ctx->err;

	ctx->hdr = hunk;
	if (!prev_hunk)
		return ICE_DDP_PKG_SUCCESS; /* no problem so far */

	for (attempt = 0; attempt < 5; attempt++) {
		if (attempt)
			msleep(20);

		err = ice_aq_download_pkg(hw, prev_hunk, ICE_PKG_BUF_SIZE,
					  prev_was_last, &offset, &info, NULL);

		aq_err = hw->adminq.sq_last_status;
		if (aq_err != ICE_AQ_RC_ENOSEC && aq_err != ICE_AQ_RC_EBADSIG)
			break;
	}

	if (err) {
		ice_debug(hw, ICE_DBG_PKG, "Pkg download failed: err %d off %d inf %d\n",
			  err, offset, info);
		ctx->err = ice_map_aq_err_to_ddp_state(aq_err);
	} else if (attempt) {
		dev_dbg(ice_hw_to_dev(hw),
			"ice_aq_download_pkg number of retries: %d\n", attempt);
	}

	return ctx->err;
}

/**
 * ice_dwnld_cfg_bufs_no_lock
 * @ctx: context of the current buffers section to send
 * @bufs: pointer to an array of buffers
 * @start: buffer index of first buffer to download
 * @count: the number of buffers to download
 *
 * Downloads package configuration buffers to the firmware. Metadata buffers
 * are skipped, and the first metadata buffer found indicates that the rest
 * of the buffers are all metadata buffers.
 */
static enum ice_ddp_state
ice_dwnld_cfg_bufs_no_lock(struct ice_ddp_send_ctx *ctx, struct ice_buf *bufs,
			   u32 start, u32 count)
{
	struct ice_buf_hdr *bh;
	enum ice_ddp_state err;

	if (!bufs || !count) {
		ice_ddp_send_ctx_set_err(ctx, ICE_DDP_PKG_ERR);
		return ICE_DDP_PKG_ERR;
	}

	bufs += start;

	for (int i = 0; i < count; i++, bufs++) {
		bh = (struct ice_buf_hdr *)bufs;
		/* Metadata buffers should not be sent to FW,
		 * their presence means "we are done here".
		 */
		if (ice_is_buffer_metadata(bh))
			break;

		err = ice_ddp_send_hunk(ctx, bh);
		if (err)
			return err;
	}

	return 0;
}

/**
 * ice_get_pkg_seg_by_idx
 * @pkg_hdr: pointer to the package header to be searched
@@ -1269,137 +1394,21 @@ ice_is_signing_seg_type_at_idx(struct ice_pkg_hdr *pkg_hdr, u32 idx,
	return false;
}

/**
 * ice_is_buffer_metadata - determine if package buffer is a metadata buffer
 * @buf: pointer to buffer header
 */
static bool ice_is_buffer_metadata(struct ice_buf_hdr *buf)
{
	if (le32_to_cpu(buf->section_entry[0].type) & ICE_METADATA_BUF)
		return true;

	return false;
}

/**
 * ice_is_last_download_buffer
 * @buf: pointer to current buffer header
 * @idx: index of the buffer in the current sequence
 * @count: the buffer count in the current sequence
 *
 * Note: this routine should only be called if the buffer is not the last buffer
 */
static bool
ice_is_last_download_buffer(struct ice_buf_hdr *buf, u32 idx, u32 count)
{
	struct ice_buf *next_buf;

	if ((idx + 1) == count)
		return true;

	/* A set metadata flag in the next buffer will signal that the current
	 * buffer will be the last buffer downloaded
	 */
	next_buf = ((struct ice_buf *)buf) + 1;

	return ice_is_buffer_metadata((struct ice_buf_hdr *)next_buf);
}

/**
 * ice_dwnld_cfg_bufs_no_lock
 * @hw: pointer to the hardware structure
 * @bufs: pointer to an array of buffers
 * @start: buffer index of first buffer to download
 * @count: the number of buffers to download
 * @indicate_last: if true, then set last buffer flag on last buffer download
 *
 * Downloads package configuration buffers to the firmware. Metadata buffers
 * are skipped, and the first metadata buffer found indicates that the rest
 * of the buffers are all metadata buffers.
 */
static enum ice_ddp_state
ice_dwnld_cfg_bufs_no_lock(struct ice_hw *hw, struct ice_buf *bufs, u32 start,
			   u32 count, bool indicate_last)
{
	enum ice_ddp_state state = ICE_DDP_PKG_SUCCESS;
	struct ice_buf_hdr *bh;
	enum ice_aq_err err;
	u32 offset, info, i;

	if (!bufs || !count)
		return ICE_DDP_PKG_ERR;

	/* If the first buffer's first section has its metadata bit set
	 * then there are no buffers to be downloaded, and the operation is
	 * considered a success.
	 */
	bh = (struct ice_buf_hdr *)(bufs + start);
	if (le32_to_cpu(bh->section_entry[0].type) & ICE_METADATA_BUF)
		return ICE_DDP_PKG_SUCCESS;

	for (i = 0; i < count; i++) {
		bool last = false;
		int try_cnt = 0;
		int status;

		bh = (struct ice_buf_hdr *)(bufs + start + i);

		if (indicate_last)
			last = ice_is_last_download_buffer(bh, i, count);

		while (1) {
			status = ice_aq_download_pkg(hw, bh, ICE_PKG_BUF_SIZE,
						     last, &offset, &info,
						     NULL);
			if (hw->adminq.sq_last_status != ICE_AQ_RC_ENOSEC &&
			    hw->adminq.sq_last_status != ICE_AQ_RC_EBADSIG)
				break;

			try_cnt++;

			if (try_cnt == 5)
				break;

			msleep(20);
		}

		if (try_cnt)
			dev_dbg(ice_hw_to_dev(hw),
				"ice_aq_download_pkg number of retries: %d\n",
				try_cnt);

		/* Save AQ status from download package */
		if (status) {
			ice_debug(hw, ICE_DBG_PKG, "Pkg download failed: err %d off %d inf %d\n",
				  status, offset, info);
			err = hw->adminq.sq_last_status;
			state = ice_map_aq_err_to_ddp_state(err);
			break;
		}

		if (last)
			break;
	}

	return state;
}

/**
 * ice_download_pkg_sig_seg - download a signature segment
 * @hw: pointer to the hardware structure
 * @ctx: context of the current buffers section to send
 * @seg: pointer to signature segment
 */
static enum ice_ddp_state
ice_download_pkg_sig_seg(struct ice_hw *hw, struct ice_sign_seg *seg)
ice_download_pkg_sig_seg(struct ice_ddp_send_ctx *ctx, struct ice_sign_seg *seg)
{
	return  ice_dwnld_cfg_bufs_no_lock(hw, seg->buf_tbl.buf_array, 0,
					   le32_to_cpu(seg->buf_tbl.buf_count),
					   false);
	return ice_dwnld_cfg_bufs_no_lock(ctx, seg->buf_tbl.buf_array, 0,
					  le32_to_cpu(seg->buf_tbl.buf_count));
}

/**
 * ice_download_pkg_config_seg - download a config segment
 * @hw: pointer to the hardware structure
 * @ctx: context of the current buffers section to send
 * @pkg_hdr: pointer to package header
 * @idx: segment index
 * @start: starting buffer
@@ -1408,8 +1417,9 @@ ice_download_pkg_sig_seg(struct ice_hw *hw, struct ice_sign_seg *seg)
 * Note: idx must reference a ICE segment
 */
static enum ice_ddp_state
ice_download_pkg_config_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr,
			    u32 idx, u32 start, u32 count)
ice_download_pkg_config_seg(struct ice_ddp_send_ctx *ctx,
			    struct ice_pkg_hdr *pkg_hdr, u32 idx, u32 start,
			    u32 count)
{
	struct ice_buf_table *bufs;
	struct ice_seg *seg;
@@ -1425,46 +1435,56 @@ ice_download_pkg_config_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr,
	if (start >= buf_count || start + count > buf_count)
		return ICE_DDP_PKG_ERR;

	return  ice_dwnld_cfg_bufs_no_lock(hw, bufs->buf_array, start, count,
					   true);
	return ice_dwnld_cfg_bufs_no_lock(ctx, bufs->buf_array, start, count);
}

static bool ice_is_last_sign_seg(u32 flags)
{
	return !(flags & ICE_SIGN_SEG_FLAGS_VALID) || /* behavior prior to valid */
	       (flags & ICE_SIGN_SEG_FLAGS_LAST);
}

/**
 * ice_dwnld_sign_and_cfg_segs - download a signing segment and config segment
 * @hw: pointer to the hardware structure
 * @ctx: context of the current buffers section to send
 * @pkg_hdr: pointer to package header
 * @idx: segment index (must be a signature segment)
 *
 * Note: idx must reference a signature segment
 */
static enum ice_ddp_state
ice_dwnld_sign_and_cfg_segs(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr,
			    u32 idx)
ice_dwnld_sign_and_cfg_segs(struct ice_ddp_send_ctx *ctx,
			    struct ice_pkg_hdr *pkg_hdr, u32 idx)
{
	u32 conf_idx, start, count, flags;
	enum ice_ddp_state state;
	struct ice_sign_seg *seg;
	u32 conf_idx;
	u32 start;
	u32 count;

	seg = (struct ice_sign_seg *)ice_get_pkg_seg_by_idx(pkg_hdr, idx);
	if (!seg) {
		state = ICE_DDP_PKG_ERR;
		goto exit;
		ice_ddp_send_ctx_set_err(ctx, state);
		return state;
	}

	count = le32_to_cpu(seg->signed_buf_count);
	state = ice_download_pkg_sig_seg(hw, seg);
	state = ice_download_pkg_sig_seg(ctx, seg);
	if (state || !count)
		goto exit;
		return state;

	conf_idx = le32_to_cpu(seg->signed_seg_idx);
	start = le32_to_cpu(seg->signed_buf_start);

	state = ice_download_pkg_config_seg(hw, pkg_hdr, conf_idx, start,
	state = ice_download_pkg_config_seg(ctx, pkg_hdr, conf_idx, start,
					    count);

exit:
	/* finish up by sending last hunk with "last" flag set if requested by
	 * DDP content
	 */
	flags = le32_to_cpu(seg->flags);
	if (ice_is_last_sign_seg(flags))
		state = ice_ddp_send_hunk(ctx, NULL);

	return state;
}

@@ -1519,6 +1539,7 @@ ice_download_pkg_with_sig_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
{
	enum ice_aq_err aq_err = hw->adminq.sq_last_status;
	enum ice_ddp_state state = ICE_DDP_PKG_ERR;
	struct ice_ddp_send_ctx ctx = { .hw = hw };
	int status;
	u32 i;

@@ -1539,7 +1560,7 @@ ice_download_pkg_with_sig_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
						    hw->pkg_sign_type))
			continue;

		state = ice_dwnld_sign_and_cfg_segs(hw, pkg_hdr, i);
		state = ice_dwnld_sign_and_cfg_segs(&ctx, pkg_hdr, i);
		if (state)
			break;
	}
@@ -1564,6 +1585,7 @@ ice_download_pkg_with_sig_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
static enum ice_ddp_state
ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
{
	struct ice_ddp_send_ctx ctx = { .hw = hw };
	enum ice_ddp_state state;
	struct ice_buf_hdr *bh;
	int status;
@@ -1576,7 +1598,7 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
	 * considered a success.
	 */
	bh = (struct ice_buf_hdr *)bufs;
	if (le32_to_cpu(bh->section_entry[0].type) & ICE_METADATA_BUF)
	if (ice_is_buffer_metadata(bh))
		return ICE_DDP_PKG_SUCCESS;

	status = ice_acquire_global_cfg_lock(hw, ICE_RES_WRITE);
@@ -1586,7 +1608,9 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
		return ice_map_aq_err_to_ddp_state(hw->adminq.sq_last_status);
	}

	state = ice_dwnld_cfg_bufs_no_lock(hw, bufs, 0, count, true);
	ice_dwnld_cfg_bufs_no_lock(&ctx, bufs, 0, count);
	/* finish up by sending last hunk with "last" flag set */
	state = ice_ddp_send_hunk(&ctx, NULL);
	if (!state)
		state = ice_post_dwnld_pkg_actions(hw);

Loading