Commit dbc0fd48 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'intel-wired-lan-driver-updates-for-2023-10-25-ice'

Jacob Keller says:

====================
Intel Wired LAN Driver Updates for 2023-10-25 (ice)

This series extends the ice driver with basic support for the E830 device
line. It does not include support for all device features, but enables basic
functionality to load and pass traffic.

Alice adds the 200G speed and PHY types supported by E830 hardware.

Dan extends the DDP package logic to support the E830 package segment.

Paul adds the basic registers and macros used by E830 hardware, and adds
support for handling variable length link status information from firmware.

Pawel removes some redundant zeroing of the PCI IDs list, and extends the
list to include the E830 device IDs.
====================

Link: https://lore.kernel.org/r/20231025214157.1222758-1-jacob.e.keller@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents edd68156 ba20ecb1
Loading
Loading
Loading
Loading
+43 −5
Original line number Diff line number Diff line
@@ -1099,7 +1099,15 @@ struct ice_aqc_get_phy_caps {
#define ICE_PHY_TYPE_HIGH_100G_CAUI2		BIT_ULL(2)
#define ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC	BIT_ULL(3)
#define ICE_PHY_TYPE_HIGH_100G_AUI2		BIT_ULL(4)
#define ICE_PHY_TYPE_HIGH_MAX_INDEX		4
#define ICE_PHY_TYPE_HIGH_200G_CR4_PAM4		BIT_ULL(5)
#define ICE_PHY_TYPE_HIGH_200G_SR4		BIT_ULL(6)
#define ICE_PHY_TYPE_HIGH_200G_FR4		BIT_ULL(7)
#define ICE_PHY_TYPE_HIGH_200G_LR4		BIT_ULL(8)
#define ICE_PHY_TYPE_HIGH_200G_DR4		BIT_ULL(9)
#define ICE_PHY_TYPE_HIGH_200G_KR4_PAM4		BIT_ULL(10)
#define ICE_PHY_TYPE_HIGH_200G_AUI4_AOC_ACC	BIT_ULL(11)
#define ICE_PHY_TYPE_HIGH_200G_AUI4		BIT_ULL(12)
#define ICE_PHY_TYPE_HIGH_MAX_INDEX		12

struct ice_aqc_get_phy_caps_data {
	__le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
@@ -1319,11 +1327,41 @@ struct ice_aqc_get_link_status_data {
#define ICE_AQ_LINK_SPEED_40GB		BIT(8)
#define ICE_AQ_LINK_SPEED_50GB		BIT(9)
#define ICE_AQ_LINK_SPEED_100GB		BIT(10)
#define ICE_AQ_LINK_SPEED_200GB		BIT(11)
#define ICE_AQ_LINK_SPEED_UNKNOWN	BIT(15)
	__le32 reserved3; /* Aligns next field to 8-byte boundary */
	__le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
	__le64 phy_type_high; /* Use values from ICE_PHY_TYPE_HIGH_* */
};
	/* Aligns next field to 8-byte boundary */
	__le16 reserved3;
	u8 ext_fec_status;
	/* RS 272 FEC enabled */
#define ICE_AQ_LINK_RS_272_FEC_EN      BIT(0)
	u8 reserved4;
	/* Use values from ICE_PHY_TYPE_LOW_* */
	__le64 phy_type_low;
	/* Use values from ICE_PHY_TYPE_HIGH_* */
	__le64 phy_type_high;
#define ICE_AQC_LS_DATA_SIZE_V1 \
	offsetofend(struct ice_aqc_get_link_status_data, phy_type_high)
	/* Get link status v2 link partner data */
	__le64 lp_phy_type_low;
	__le64 lp_phy_type_high;
	u8 lp_fec_adv;
#define ICE_AQ_LINK_LP_10G_KR_FEC_CAP  BIT(0)
#define ICE_AQ_LINK_LP_25G_KR_FEC_CAP  BIT(1)
#define ICE_AQ_LINK_LP_RS_528_FEC_CAP  BIT(2)
#define ICE_AQ_LINK_LP_50G_KR_272_FEC_CAP BIT(3)
#define ICE_AQ_LINK_LP_100G_KR_272_FEC_CAP BIT(4)
#define ICE_AQ_LINK_LP_200G_KR_272_FEC_CAP BIT(5)
	u8 lp_fec_req;
#define ICE_AQ_LINK_LP_10G_KR_FEC_REQ  BIT(0)
#define ICE_AQ_LINK_LP_25G_KR_FEC_REQ  BIT(1)
#define ICE_AQ_LINK_LP_RS_528_FEC_REQ  BIT(2)
#define ICE_AQ_LINK_LP_KR_272_FEC_REQ  BIT(3)
	u8 lp_flowcontrol;
#define ICE_AQ_LINK_LP_PAUSE_ADV       BIT(0)
#define ICE_AQ_LINK_LP_ASM_DIR_ADV     BIT(1)
#define ICE_AQC_LS_DATA_SIZE_V2 \
	offsetofend(struct ice_aqc_get_link_status_data, lp_flowcontrol)
} __packed;

/* Set event mask command (direct 0x0613) */
struct ice_aqc_set_event_mask {
+68 −26
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018, Intel Corporation. */
/* Copyright (c) 2018-2023, Intel Corporation. */

#include "ice_common.h"
#include "ice_sched.h"
@@ -154,6 +154,12 @@ static int ice_set_mac_type(struct ice_hw *hw)
	case ICE_DEV_ID_E823L_SFP:
		hw->mac_type = ICE_MAC_GENERIC;
		break;
	case ICE_DEV_ID_E830_BACKPLANE:
	case ICE_DEV_ID_E830_QSFP56:
	case ICE_DEV_ID_E830_SFP:
	case ICE_DEV_ID_E830_SFP_DD:
		hw->mac_type = ICE_MAC_E830;
		break;
	default:
		hw->mac_type = ICE_MAC_UNKNOWN;
		break;
@@ -645,6 +651,24 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
	return ICE_MEDIA_UNKNOWN;
}

/**
 * ice_get_link_status_datalen
 * @hw: pointer to the HW struct
 *
 * Returns datalength for the Get Link Status AQ command, which is bigger for
 * newer adapter families handled by ice driver.
 */
static u16 ice_get_link_status_datalen(struct ice_hw *hw)
{
	switch (hw->mac_type) {
	case ICE_MAC_E830:
		return ICE_AQC_LS_DATA_SIZE_V2;
	case ICE_MAC_E810:
	default:
		return ICE_AQC_LS_DATA_SIZE_V1;
	}
}

/**
 * ice_aq_get_link_info
 * @pi: port information structure
@@ -683,8 +707,8 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
	resp->cmd_flags = cpu_to_le16(cmd_flags);
	resp->lport_num = pi->lport;

	status = ice_aq_send_cmd(hw, &desc, &link_data, sizeof(link_data), cd);

	status = ice_aq_send_cmd(hw, &desc, &link_data,
				 ice_get_link_status_datalen(hw), cd);
	if (status)
		return status;

@@ -759,8 +783,7 @@ static void
ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
				struct ice_aqc_set_mac_cfg *cmd)
{
	u16 fc_thres_val, tx_timer_val;
	u32 val;
	u32 val, fc_thres_m;

	/* We read back the transmit timer and FC threshold value of
	 * LFC. Thus, we will use index =
@@ -769,19 +792,32 @@ ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
	 * Also, because we are operating on transmit timer and FC
	 * threshold of LFC, we don't turn on any bit in tx_tmr_priority
	 */
#define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX
#define E800_IDX_OF_LFC E800_PRTMAC_HSEC_CTL_TX_PS_QNT_MAX
#define E800_REFRESH_TMR E800_PRTMAC_HSEC_CTL_TX_PS_RFSH_TMR

	if (hw->mac_type == ICE_MAC_E830) {
		/* Retrieve the transmit timer */
	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(IDX_OF_LFC));
	tx_timer_val = val &
		PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M;
	cmd->tx_tmr_value = cpu_to_le16(tx_timer_val);
		val = rd32(hw, E830_PRTMAC_CL01_PS_QNT);
		cmd->tx_tmr_value =
			le16_encode_bits(val, E830_PRTMAC_CL01_PS_QNT_CL0_M);

	/* Retrieve the FC threshold */
	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(IDX_OF_LFC));
	fc_thres_val = val & PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M;
		/* Retrieve the fc threshold */
		val = rd32(hw, E830_PRTMAC_CL01_QNT_THR);
		fc_thres_m = E830_PRTMAC_CL01_QNT_THR_CL0_M;
	} else {
		/* Retrieve the transmit timer */
		val = rd32(hw,
			   E800_PRTMAC_HSEC_CTL_TX_PS_QNT(E800_IDX_OF_LFC));
		cmd->tx_tmr_value =
			le16_encode_bits(val,
					 E800_PRTMAC_HSEC_CTL_TX_PS_QNT_M);

	cmd->fc_refresh_threshold = cpu_to_le16(fc_thres_val);
		/* Retrieve the fc threshold */
		val = rd32(hw,
			   E800_REFRESH_TMR(E800_IDX_OF_LFC));
		fc_thres_m = E800_PRTMAC_HSEC_CTL_TX_PS_RFSH_TMR_M;
	}
	cmd->fc_refresh_threshold = le16_encode_bits(val, fc_thres_m);
}

/**
@@ -2464,16 +2500,21 @@ ice_parse_1588_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
static void
ice_parse_fdir_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p)
{
	u32 reg_val, val;
	u32 reg_val, gsize, bsize;

	reg_val = rd32(hw, GLQF_FD_SIZE);
	val = (reg_val & GLQF_FD_SIZE_FD_GSIZE_M) >>
		GLQF_FD_SIZE_FD_GSIZE_S;
	func_p->fd_fltr_guar =
		ice_get_num_per_func(hw, val);
	val = (reg_val & GLQF_FD_SIZE_FD_BSIZE_M) >>
		GLQF_FD_SIZE_FD_BSIZE_S;
	func_p->fd_fltr_best_effort = val;
	switch (hw->mac_type) {
	case ICE_MAC_E830:
		gsize = FIELD_GET(E830_GLQF_FD_SIZE_FD_GSIZE_M, reg_val);
		bsize = FIELD_GET(E830_GLQF_FD_SIZE_FD_BSIZE_M, reg_val);
		break;
	case ICE_MAC_E810:
	default:
		gsize = FIELD_GET(E800_GLQF_FD_SIZE_FD_GSIZE_M, reg_val);
		bsize = FIELD_GET(E800_GLQF_FD_SIZE_FD_BSIZE_M, reg_val);
	}
	func_p->fd_fltr_guar = ice_get_num_per_func(hw, gsize);
	func_p->fd_fltr_best_effort = bsize;

	ice_debug(hw, ICE_DBG_INIT, "func caps: fd_fltr_guar = %d\n",
		  func_p->fd_fltr_guar);
@@ -6069,6 +6110,7 @@ static const u32 ice_aq_to_link_speed[] = {
	SPEED_40000,
	SPEED_50000,
	SPEED_100000,	/* BIT(10) */
	SPEED_200000,
};

/**
+354 −72
Original line number Diff line number Diff line
@@ -1201,23 +1201,120 @@ ice_aq_download_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf,
}

/**
 * ice_dwnld_cfg_bufs
 * ice_get_pkg_seg_by_idx
 * @pkg_hdr: pointer to the package header to be searched
 * @idx: index of segment
 */
static struct ice_generic_seg_hdr *
ice_get_pkg_seg_by_idx(struct ice_pkg_hdr *pkg_hdr, u32 idx)
{
	if (idx < le32_to_cpu(pkg_hdr->seg_count))
		return (struct ice_generic_seg_hdr *)
			((u8 *)pkg_hdr +
			 le32_to_cpu(pkg_hdr->seg_offset[idx]));

	return NULL;
}

/**
 * ice_is_signing_seg_at_idx - determine if segment is a signing segment
 * @pkg_hdr: pointer to package header
 * @idx: segment index
 */
static bool ice_is_signing_seg_at_idx(struct ice_pkg_hdr *pkg_hdr, u32 idx)
{
	struct ice_generic_seg_hdr *seg;

	seg = ice_get_pkg_seg_by_idx(pkg_hdr, idx);
	if (!seg)
		return false;

	return le32_to_cpu(seg->seg_type) == SEGMENT_TYPE_SIGNING;
}

/**
 * ice_is_signing_seg_type_at_idx
 * @pkg_hdr: pointer to package header
 * @idx: segment index
 * @seg_id: segment id that is expected
 * @sign_type: signing type
 *
 * Determine if a segment is a signing segment of the correct type
 */
static bool
ice_is_signing_seg_type_at_idx(struct ice_pkg_hdr *pkg_hdr, u32 idx,
			       u32 seg_id, u32 sign_type)
{
	struct ice_sign_seg *seg;

	if (!ice_is_signing_seg_at_idx(pkg_hdr, idx))
		return false;

	seg = (struct ice_sign_seg *)ice_get_pkg_seg_by_idx(pkg_hdr, idx);

	if (seg && le32_to_cpu(seg->seg_id) == seg_id &&
	    le32_to_cpu(seg->sign_type) == sign_type)
		return true;

	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
 * @count: the number of buffers in the array
 * @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
 *
 * Obtains global config lock and downloads the 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.
 * 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(struct ice_hw *hw,
					     struct ice_buf *bufs, u32 count)
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;
	int status;

	if (!bufs || !count)
		return ICE_DDP_PKG_ERR;
@@ -1226,43 +1323,25 @@ static enum ice_ddp_state ice_dwnld_cfg_bufs(struct ice_hw *hw,
	 * then there are no buffers to be downloaded, and the operation is
	 * considered a success.
	 */
	bh = (struct ice_buf_hdr *)bufs;
	bh = (struct ice_buf_hdr *)(bufs + start);
	if (le32_to_cpu(bh->section_entry[0].type) & ICE_METADATA_BUF)
		return ICE_DDP_PKG_SUCCESS;

	status = ice_acquire_global_cfg_lock(hw, ICE_RES_WRITE);
	if (status) {
		if (status == -EALREADY)
			return ICE_DDP_PKG_ALREADY_LOADED;
		return ice_map_aq_err_to_ddp_state(hw->adminq.sq_last_status);
	}

	for (i = 0; i < count; i++) {
		bool last = ((i + 1) == count);

		if (!last) {
			/* check next buffer for metadata flag */
			bh = (struct ice_buf_hdr *)(bufs + i + 1);
		bool last = false;
		int status;

			/* A set metadata flag in the next buffer will signal
			 * that the current buffer will be the last buffer
			 * downloaded
			 */
			if (le16_to_cpu(bh->section_count))
				if (le32_to_cpu(bh->section_entry[0].type) &
				    ICE_METADATA_BUF)
					last = true;
		}
		bh = (struct ice_buf_hdr *)(bufs + start + i);

		bh = (struct ice_buf_hdr *)(bufs + i);
		if (indicate_last)
			last = ice_is_last_download_buffer(bh, i, count);

		status = ice_aq_download_pkg(hw, bh, ICE_PKG_BUF_SIZE, last,
					     &offset, &info, NULL);

		/* Save AQ status from download package */
		if (status) {
			ice_debug(hw, ICE_DBG_PKG,
				  "Pkg download failed: err %d off %d inf %d\n",
			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);
@@ -1273,72 +1352,196 @@ static enum ice_ddp_state ice_dwnld_cfg_bufs(struct ice_hw *hw,
			break;
	}

	if (!status) {
		status = ice_set_vlan_mode(hw);
		if (status)
			ice_debug(hw, ICE_DBG_PKG,
				  "Failed to set VLAN mode: err %d\n", status);
	return state;
}

	ice_release_global_cfg_lock(hw);
/**
 * ice_download_pkg_sig_seg - download a signature segment
 * @hw: pointer to the hardware structure
 * @seg: pointer to signature segment
 */
static enum ice_ddp_state
ice_download_pkg_sig_seg(struct ice_hw *hw, 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 state;
/**
 * ice_download_pkg_config_seg - download a config segment
 * @hw: pointer to the hardware structure
 * @pkg_hdr: pointer to package header
 * @idx: segment index
 * @start: starting buffer
 * @count: buffer count
 *
 * 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)
{
	struct ice_buf_table *bufs;
	struct ice_seg *seg;
	u32 buf_count;

	seg = (struct ice_seg *)ice_get_pkg_seg_by_idx(pkg_hdr, idx);
	if (!seg)
		return ICE_DDP_PKG_ERR;

	bufs = ice_find_buf_table(seg);
	buf_count = le32_to_cpu(bufs->buf_count);

	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);
}

/**
 * ice_aq_get_pkg_info_list
 * ice_dwnld_sign_and_cfg_segs - download a signing segment and config segment
 * @hw: pointer to the hardware structure
 * @pkg_info: the buffer which will receive the information list
 * @buf_size: the size of the pkg_info information buffer
 * @cd: pointer to command details structure or NULL
 * @pkg_hdr: pointer to package header
 * @idx: segment index (must be a signature segment)
 *
 * Get Package Info List (0x0C43)
 * Note: idx must reference a signature segment
 */
static int ice_aq_get_pkg_info_list(struct ice_hw *hw,
				    struct ice_aqc_get_pkg_info_resp *pkg_info,
				    u16 buf_size, struct ice_sq_cd *cd)
static enum ice_ddp_state
ice_dwnld_sign_and_cfg_segs(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr,
			    u32 idx)
{
	struct ice_aq_desc desc;
	enum ice_ddp_state state;
	struct ice_sign_seg *seg;
	u32 conf_idx;
	u32 start;
	u32 count;

	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_pkg_info_list);
	seg = (struct ice_sign_seg *)ice_get_pkg_seg_by_idx(pkg_hdr, idx);
	if (!seg) {
		state = ICE_DDP_PKG_ERR;
		goto exit;
	}

	return ice_aq_send_cmd(hw, &desc, pkg_info, buf_size, cd);
	conf_idx = le32_to_cpu(seg->signed_seg_idx);
	start = le32_to_cpu(seg->signed_buf_start);
	count = le32_to_cpu(seg->signed_buf_count);

	state = ice_download_pkg_sig_seg(hw, seg);
	if (state)
		goto exit;

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

exit:
	return state;
}

/**
 * ice_match_signing_seg - determine if a matching signing segment exists
 * @pkg_hdr: pointer to package header
 * @seg_id: segment id that is expected
 * @sign_type: signing type
 */
static bool
ice_match_signing_seg(struct ice_pkg_hdr *pkg_hdr, u32 seg_id, u32 sign_type)
{
	u32 i;

	for (i = 0; i < le32_to_cpu(pkg_hdr->seg_count); i++) {
		if (ice_is_signing_seg_type_at_idx(pkg_hdr, i, seg_id,
						   sign_type))
			return true;
	}

	return false;
}

/**
 * ice_post_dwnld_pkg_actions - perform post download package actions
 * @hw: pointer to the hardware structure
 */
static enum ice_ddp_state
ice_post_dwnld_pkg_actions(struct ice_hw *hw)
{
	int status;

	status = ice_set_vlan_mode(hw);
	if (status) {
		ice_debug(hw, ICE_DBG_PKG, "Failed to set VLAN mode: err %d\n",
			  status);
		return ICE_DDP_PKG_ERR;
	}

	return ICE_DDP_PKG_SUCCESS;
}

/**
 * ice_download_pkg
 * @hw: pointer to the hardware structure
 * @ice_seg: pointer to the segment of the package to be downloaded
 * @pkg_hdr: pointer to package header
 *
 * Handles the download of a complete package.
 */
static enum ice_ddp_state ice_download_pkg(struct ice_hw *hw,
					   struct ice_seg *ice_seg)
static enum ice_ddp_state
ice_download_pkg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
{
	struct ice_buf_table *ice_buf_tbl;
	enum ice_aq_err aq_err = hw->adminq.sq_last_status;
	enum ice_ddp_state state = ICE_DDP_PKG_ERR;
	int status;
	u32 i;

	ice_debug(hw, ICE_DBG_PKG, "Segment format version: %d.%d.%d.%d\n",
		  ice_seg->hdr.seg_format_ver.major,
		  ice_seg->hdr.seg_format_ver.minor,
		  ice_seg->hdr.seg_format_ver.update,
		  ice_seg->hdr.seg_format_ver.draft);
	ice_debug(hw, ICE_DBG_INIT, "Segment ID %d\n", hw->pkg_seg_id);
	ice_debug(hw, ICE_DBG_INIT, "Signature type %d\n", hw->pkg_sign_type);

	ice_debug(hw, ICE_DBG_PKG, "Seg: type 0x%X, size %d, name %s\n",
		  le32_to_cpu(ice_seg->hdr.seg_type),
		  le32_to_cpu(ice_seg->hdr.seg_size), ice_seg->hdr.seg_id);
	status = ice_acquire_global_cfg_lock(hw, ICE_RES_WRITE);
	if (status) {
		if (status == -EALREADY)
			state = ICE_DDP_PKG_ALREADY_LOADED;
		else
			state = ice_map_aq_err_to_ddp_state(aq_err);
		return state;
	}

	ice_buf_tbl = ice_find_buf_table(ice_seg);
	for (i = 0; i < le32_to_cpu(pkg_hdr->seg_count); i++) {
		if (!ice_is_signing_seg_type_at_idx(pkg_hdr, i, hw->pkg_seg_id,
						    hw->pkg_sign_type))
			continue;

	ice_debug(hw, ICE_DBG_PKG, "Seg buf count: %d\n",
		  le32_to_cpu(ice_buf_tbl->buf_count));
		state = ice_dwnld_sign_and_cfg_segs(hw, pkg_hdr, i);
		if (state)
			break;
	}

	status = ice_dwnld_cfg_bufs(hw, ice_buf_tbl->buf_array,
				    le32_to_cpu(ice_buf_tbl->buf_count));
	if (!state)
		state = ice_post_dwnld_pkg_actions(hw);

	ice_release_global_cfg_lock(hw);
	ice_post_pkg_dwnld_vlan_mode_cfg(hw);

	return status;
	return state;
}

/**
 * ice_aq_get_pkg_info_list
 * @hw: pointer to the hardware structure
 * @pkg_info: the buffer which will receive the information list
 * @buf_size: the size of the pkg_info information buffer
 * @cd: pointer to command details structure or NULL
 *
 * Get Package Info List (0x0C43)
 */
static int ice_aq_get_pkg_info_list(struct ice_hw *hw,
				    struct ice_aqc_get_pkg_info_resp *pkg_info,
				    u16 buf_size, struct ice_sq_cd *cd)
{
	struct ice_aq_desc desc;

	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_pkg_info_list);

	return ice_aq_send_cmd(hw, &desc, pkg_info, buf_size, cd);
}

/**
@@ -1497,6 +1700,73 @@ ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type,
	return NULL;
}

/**
 * ice_has_signing_seg - determine if package has a signing segment
 * @hw: pointer to the hardware structure
 * @pkg_hdr: pointer to the driver's package hdr
 */
static bool ice_has_signing_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
{
	struct ice_generic_seg_hdr *seg_hdr;

	seg_hdr = (struct ice_generic_seg_hdr *)
		ice_find_seg_in_pkg(hw, SEGMENT_TYPE_SIGNING, pkg_hdr);

	return seg_hdr ? true : false;
}

/**
 * ice_get_pkg_segment_id - get correct package segment id, based on device
 * @mac_type: MAC type of the device
 */
static u32 ice_get_pkg_segment_id(enum ice_mac_type mac_type)
{
	u32 seg_id;

	switch (mac_type) {
	case ICE_MAC_E830:
		seg_id = SEGMENT_TYPE_ICE_E830;
		break;
	case ICE_MAC_GENERIC:
	default:
		seg_id = SEGMENT_TYPE_ICE_E810;
		break;
	}

	return seg_id;
}

/**
 * ice_get_pkg_sign_type - get package segment sign type, based on device
 * @mac_type: MAC type of the device
 */
static u32 ice_get_pkg_sign_type(enum ice_mac_type mac_type)
{
	u32 sign_type;

	switch (mac_type) {
	case ICE_MAC_E830:
		sign_type = SEGMENT_SIGN_TYPE_RSA3K_SBB;
		break;
	case ICE_MAC_GENERIC:
	default:
		sign_type = SEGMENT_SIGN_TYPE_RSA2K;
		break;
	}

	return sign_type;
}

/**
 * ice_get_signing_req - get correct package requirements, based on device
 * @hw: pointer to the hardware structure
 */
static void ice_get_signing_req(struct ice_hw *hw)
{
	hw->pkg_seg_id = ice_get_pkg_segment_id(hw->mac_type);
	hw->pkg_sign_type = ice_get_pkg_sign_type(hw->mac_type);
}

/**
 * ice_init_pkg_info
 * @hw: pointer to the hardware structure
@@ -1512,7 +1782,14 @@ static enum ice_ddp_state ice_init_pkg_info(struct ice_hw *hw,
	if (!pkg_hdr)
		return ICE_DDP_PKG_ERR;

	seg_hdr = ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, pkg_hdr);
	hw->pkg_has_signing_seg = ice_has_signing_seg(hw, pkg_hdr);
	ice_get_signing_req(hw);

	ice_debug(hw, ICE_DBG_INIT, "Pkg using segment id: 0x%08X\n",
		  hw->pkg_seg_id);

	seg_hdr = (struct ice_generic_seg_hdr *)
		ice_find_seg_in_pkg(hw, hw->pkg_seg_id, pkg_hdr);
	if (seg_hdr) {
		struct ice_meta_sect *meta;
		struct ice_pkg_enum state;
@@ -1626,7 +1903,7 @@ static enum ice_ddp_state ice_chk_pkg_compat(struct ice_hw *hw,
	}

	/* find ICE segment in given package */
	*seg = (struct ice_seg *)ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE,
	*seg = (struct ice_seg *)ice_find_seg_in_pkg(hw, hw->pkg_seg_id,
						     ospkg);
	if (!*seg) {
		ice_debug(hw, ICE_DBG_INIT, "no ice segment in package.\n");
@@ -1792,6 +2069,11 @@ enum ice_ddp_state ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)
	if (state)
		return state;

	/* must be a matching segment */
	if (hw->pkg_has_signing_seg &&
	    !ice_match_signing_seg(pkg, hw->pkg_seg_id, hw->pkg_sign_type))
		return ICE_DDP_PKG_ERR;

	/* before downloading the package, check package version for
	 * compatibility with driver
	 */
@@ -1801,7 +2083,7 @@ enum ice_ddp_state ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)

	/* initialize package hints and then download package */
	ice_init_pkg_hints(hw, seg);
	state = ice_download_pkg(hw, seg);
	state = ice_download_pkg(hw, pkg);
	if (state == ICE_DDP_PKG_ALREADY_LOADED) {
		ice_debug(hw, ICE_DBG_INIT,
			  "package previously loaded - no work.\n");
+25 −2
Original line number Diff line number Diff line
@@ -98,10 +98,21 @@ struct ice_pkg_hdr {
	__le32 seg_offset[];
};

/* Package signing algorithm types */
#define SEGMENT_SIGN_TYPE_INVALID	0x00000000
#define SEGMENT_SIGN_TYPE_RSA2K		0x00000001
#define SEGMENT_SIGN_TYPE_RSA3K		0x00000002
#define SEGMENT_SIGN_TYPE_RSA3K_SBB	0x00000003 /* Secure Boot Block */
#define SEGMENT_SIGN_TYPE_RSA3K_E825	0x00000005

/* generic segment */
struct ice_generic_seg_hdr {
#define SEGMENT_TYPE_INVALID	0x00000000
#define SEGMENT_TYPE_METADATA	0x00000001
#define SEGMENT_TYPE_ICE 0x00000010
#define SEGMENT_TYPE_ICE_E810	0x00000010
#define SEGMENT_TYPE_SIGNING	0x00001001
#define SEGMENT_TYPE_ICE_RUN_TIME_CFG 0x00000020
#define SEGMENT_TYPE_ICE_E830	0x00000017
	__le32 seg_type;
	struct ice_pkg_ver seg_format_ver;
	__le32 seg_size;
@@ -163,6 +174,18 @@ struct ice_global_metadata_seg {
#define ICE_MIN_S_SZ 1
#define ICE_MAX_S_SZ 4084

struct ice_sign_seg {
	struct ice_generic_seg_hdr hdr;
	__le32 seg_id;
	__le32 sign_type;
	__le32 signed_seg_idx;
	__le32 signed_buf_start;
	__le32 signed_buf_count;
#define ICE_SIGN_SEG_RESERVED_COUNT	44
	u8 reserved[ICE_SIGN_SEG_RESERVED_COUNT];
	struct ice_buf_table buf_tbl;
};

/* section information */
struct ice_section_entry {
	__le32 type;
+9 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018, Intel Corporation. */
/* Copyright (c) 2018-2023, Intel Corporation. */

#ifndef _ICE_DEVIDS_H_
#define _ICE_DEVIDS_H_
@@ -16,6 +16,14 @@
#define ICE_DEV_ID_E823L_1GBE		0x124F
/* Intel(R) Ethernet Connection E823-L for QSFP */
#define ICE_DEV_ID_E823L_QSFP		0x151D
/* Intel(R) Ethernet Controller E830-C for backplane */
#define ICE_DEV_ID_E830_BACKPLANE	0x12D1
/* Intel(R) Ethernet Controller E830-C for QSFP */
#define ICE_DEV_ID_E830_QSFP56		0x12D2
/* Intel(R) Ethernet Controller E830-C for SFP */
#define ICE_DEV_ID_E830_SFP		0x12D3
/* Intel(R) Ethernet Controller E830-C for SFP-DD */
#define ICE_DEV_ID_E830_SFP_DD		0x12D4
/* Intel(R) Ethernet Controller E810-C for backplane */
#define ICE_DEV_ID_E810C_BACKPLANE	0x1591
/* Intel(R) Ethernet Controller E810-C for QSFP */
Loading