Commit 4654ec61 authored by Jedrzej Jagielski's avatar Jedrzej Jagielski Committed by Tony Nguyen
Browse files

ixgbe: add E610 functions getting PBA and FW ver info



Introduce 2 E610 specific callbacks implementations:
-ixgbe_start_hw_e610() which expands the regular .start_hw callback with
getting FW version information
-ixgbe_read_pba_string_e610() which gets Product Board Assembly string

Extend EEPROM ops with new .read_pba_string in order to distinguish
generic one and the E610 one.

Reviewed-by: default avatarMateusz Polchlopek <mateusz.polchlopek@intel.com>
Tested-by: default avatarBharath R <bharath.r@intel.com>
Co-developed-by: default avatarStefan Wegrzyn <stefan.wegrzyn@intel.com>
Signed-off-by: default avatarStefan Wegrzyn <stefan.wegrzyn@intel.com>
Signed-off-by: default avatarJedrzej Jagielski <jedrzej.jagielski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 8210ff73
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -196,7 +196,7 @@ static int ixgbe_devlink_info_get(struct devlink *devlink,
	if (err)
		goto free_ctx;

	err = ixgbe_read_pba_string_generic(hw, ctx->buf, sizeof(ctx->buf));
	err = hw->eeprom.ops.read_pba_string(hw, ctx->buf, sizeof(ctx->buf));
	if (err)
		goto free_ctx;

+1 −0
Original line number Diff line number Diff line
@@ -1169,6 +1169,7 @@ static const struct ixgbe_eeprom_operations eeprom_ops_82598 = {
	.calc_checksum          = &ixgbe_calc_eeprom_checksum_generic,
	.validate_checksum	= &ixgbe_validate_eeprom_checksum_generic,
	.update_checksum	= &ixgbe_update_eeprom_checksum_generic,
	.read_pba_string        = &ixgbe_read_pba_string_generic,
};

static const struct ixgbe_phy_operations phy_ops_82598 = {
+1 −0
Original line number Diff line number Diff line
@@ -2230,6 +2230,7 @@ static const struct ixgbe_eeprom_operations eeprom_ops_82599 = {
	.calc_checksum		= &ixgbe_calc_eeprom_checksum_generic,
	.validate_checksum	= &ixgbe_validate_eeprom_checksum_generic,
	.update_checksum	= &ixgbe_update_eeprom_checksum_generic,
	.read_pba_string        = &ixgbe_read_pba_string_generic,
};

static const struct ixgbe_phy_operations phy_ops_82599 = {
+1 −0
Original line number Diff line number Diff line
@@ -332,6 +332,7 @@ int ixgbe_start_hw_generic(struct ixgbe_hw *hw)
 * Devices in the second generation:
 *     82599
 *     X540
 *     E610
 **/
int ixgbe_start_hw_gen2(struct ixgbe_hw *hw)
{
+183 −1
Original line number Diff line number Diff line
@@ -343,6 +343,40 @@ void ixgbe_fill_dflt_direct_cmd_desc(struct ixgbe_aci_desc *desc, u16 opcode)
	desc->flags = cpu_to_le16(IXGBE_ACI_FLAG_SI);
}

/**
 * ixgbe_aci_get_fw_ver - Get the firmware version
 * @hw: pointer to the HW struct
 *
 * Get the firmware version using ACI command (0x0001).
 *
 * Return: the exit code of the operation.
 */
static int ixgbe_aci_get_fw_ver(struct ixgbe_hw *hw)
{
	struct ixgbe_aci_cmd_get_ver *resp;
	struct ixgbe_aci_desc desc;
	int err;

	resp = &desc.params.get_ver;

	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_ver);

	err = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
	if (!err) {
		hw->fw_branch = resp->fw_branch;
		hw->fw_maj_ver = resp->fw_major;
		hw->fw_min_ver = resp->fw_minor;
		hw->fw_patch = resp->fw_patch;
		hw->fw_build = le32_to_cpu(resp->fw_build);
		hw->api_branch = resp->api_branch;
		hw->api_maj_ver = resp->api_major;
		hw->api_min_ver = resp->api_minor;
		hw->api_patch = resp->api_patch;
	}

	return err;
}

/**
 * ixgbe_aci_req_res - request a common resource
 * @hw: pointer to the HW struct
@@ -1410,6 +1444,32 @@ int ixgbe_configure_lse(struct ixgbe_hw *hw, bool activate, u16 mask)
	return ixgbe_aci_get_link_info(hw, activate, NULL);
}

/**
 * ixgbe_start_hw_e610 - Prepare hardware for Tx/Rx
 * @hw: pointer to hardware structure
 *
 * Get firmware version and start the hardware using the generic
 * start_hw() and ixgbe_start_hw_gen2() functions.
 *
 * Return: the exit code of the operation.
 */
static int ixgbe_start_hw_e610(struct ixgbe_hw *hw)
{
	int err;

	err = ixgbe_aci_get_fw_ver(hw);
	if (err)
		return err;

	err = ixgbe_start_hw_generic(hw);
	if (err)
		return err;

	ixgbe_start_hw_gen2(hw);

	return 0;
}

/**
 * ixgbe_get_media_type_e610 - Gets media type
 * @hw: pointer to the HW struct
@@ -3366,9 +3426,129 @@ int ixgbe_reset_hw_e610(struct ixgbe_hw *hw)
	return err;
}

/**
 * ixgbe_get_pfa_module_tlv - Read sub module TLV from NVM PFA
 * @hw: pointer to hardware structure
 * @module_tlv: pointer to module TLV to return
 * @module_tlv_len: pointer to module TLV length to return
 * @module_type: module type requested
 *
 * Find the requested sub module TLV type from the Preserved Field
 * Area (PFA) and returns the TLV pointer and length. The caller can
 * use these to read the variable length TLV value.
 *
 * Return: the exit code of the operation.
 */
static int ixgbe_get_pfa_module_tlv(struct ixgbe_hw *hw, u16 *module_tlv,
				    u16 *module_tlv_len, u16 module_type)
{
	u16 pfa_len, pfa_ptr, pfa_end_ptr;
	u16 next_tlv;
	int err;

	err = ixgbe_read_ee_aci_e610(hw, IXGBE_E610_SR_PFA_PTR, &pfa_ptr);
	if (err)
		return err;

	err = ixgbe_read_ee_aci_e610(hw, pfa_ptr, &pfa_len);
	if (err)
		return err;

	/* Starting with first TLV after PFA length, iterate through the list
	 * of TLVs to find the requested one.
	 */
	next_tlv = pfa_ptr + 1;
	pfa_end_ptr = pfa_ptr + pfa_len;
	while (next_tlv < pfa_end_ptr) {
		u16 tlv_sub_module_type, tlv_len;

		/* Read TLV type */
		err = ixgbe_read_ee_aci_e610(hw, next_tlv,
					     &tlv_sub_module_type);
		if (err)
			break;

		/* Read TLV length */
		err = ixgbe_read_ee_aci_e610(hw, next_tlv + 1, &tlv_len);
		if (err)
			break;

		if (tlv_sub_module_type == module_type) {
			if (tlv_len) {
				*module_tlv = next_tlv;
				*module_tlv_len = tlv_len;
				return 0;
			}
			return -EIO;
		}
		/* Check next TLV, i.e. current TLV pointer + length + 2 words
		 * (for current TLV's type and length).
		 */
		next_tlv = next_tlv + tlv_len + 2;
	}
	/* Module does not exist */
	return -ENODATA;
}

/**
 * ixgbe_read_pba_string_e610 - Read PBA string from NVM
 * @hw: pointer to hardware structure
 * @pba_num: stores the part number string from the NVM
 * @pba_num_size: part number string buffer length
 *
 * Read the part number string from the NVM.
 *
 * Return: the exit code of the operation.
 */
static int ixgbe_read_pba_string_e610(struct ixgbe_hw *hw, u8 *pba_num,
				      u32 pba_num_size)
{
	u16 pba_tlv, pba_tlv_len;
	u16 pba_word, pba_size;
	int err;

	*pba_num = '\0';

	err = ixgbe_get_pfa_module_tlv(hw, &pba_tlv, &pba_tlv_len,
				       IXGBE_E610_SR_PBA_BLOCK_PTR);
	if (err)
		return err;

	/* pba_size is the next word */
	err = ixgbe_read_ee_aci_e610(hw, (pba_tlv + 2), &pba_size);
	if (err)
		return err;

	if (pba_tlv_len < pba_size)
		return -EINVAL;

	/* Subtract one to get PBA word count (PBA Size word is included in
	 * total size).
	 */
	pba_size--;

	if (pba_num_size < (((u32)pba_size * 2) + 1))
		return -EINVAL;

	for (u16 i = 0; i < pba_size; i++) {
		err = ixgbe_read_ee_aci_e610(hw, (pba_tlv + 2 + 1) + i,
					     &pba_word);
		if (err)
			return err;

		pba_num[(i * 2)] = FIELD_GET(IXGBE_E610_SR_PBA_BLOCK_MASK,
					     pba_word);
		pba_num[(i * 2) + 1] = pba_word & 0xFF;
	}

	pba_num[(pba_size * 2)] = '\0';

	return err;
}

static const struct ixgbe_mac_operations mac_ops_e610 = {
	.init_hw			= ixgbe_init_hw_generic,
	.start_hw			= ixgbe_start_hw_X540,
	.start_hw			= ixgbe_start_hw_e610,
	.clear_hw_cntrs			= ixgbe_clear_hw_cntrs_generic,
	.enable_rx_dma			= ixgbe_enable_rx_dma_generic,
	.get_mac_addr			= ixgbe_get_mac_addr_generic,
@@ -3433,6 +3613,8 @@ static const struct ixgbe_eeprom_operations eeprom_ops_e610 = {
	.read				= ixgbe_read_ee_aci_e610,
	.read_buffer			= ixgbe_read_ee_aci_buffer_e610,
	.validate_checksum		= ixgbe_validate_eeprom_checksum_e610,
	.read_pba_string		= ixgbe_read_pba_string_e610,
	.init_params			= ixgbe_init_eeprom_params_e610,
};

const struct ixgbe_info ixgbe_e610_info = {
Loading