[Intel-wired-lan] [next PATCH S78-V4 02/12] i40e: Fix reporting of supported link modes

Shannon Nelson shannon.nelson at oracle.com
Mon Aug 7 17:18:49 UTC 2017


On 8/4/2017 6:52 AM, Alice Michael wrote:
> From: Filip Sadowski <filip.sadowski at intel.com>
> 
> This patch fixes incorrect reporting of supported link modes on some NICs.
> 
> Signed-off-by: Filip Sadowski <filip.sadowski at intel.com>
> ---
>   drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h   | 20 ++++++++++++++++++--
>   drivers/net/ethernet/intel/i40e/i40e_common.c       |  8 +++++++-
>   drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 20 ++++++++++++++++++--
>   3 files changed, 43 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
> index e2a9ec8..5d0291c 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
> @@ -1734,6 +1734,8 @@ enum i40e_aq_phy_type {
>   	I40E_PHY_TYPE_10GBASE_CR1_CU		= 0xB,
>   	I40E_PHY_TYPE_10GBASE_AOC		= 0xC,
>   	I40E_PHY_TYPE_40GBASE_AOC		= 0xD,
> +	I40E_PHY_TYPE_UNRECOGNIZED		= 0xE,
> +	I40E_PHY_TYPE_UNSUPPORTED		= 0xF,
>   	I40E_PHY_TYPE_100BASE_TX		= 0x11,
>   	I40E_PHY_TYPE_1000BASE_T		= 0x12,
>   	I40E_PHY_TYPE_10GBASE_T			= 0x13,
> @@ -1752,6 +1754,8 @@ enum i40e_aq_phy_type {
>   	I40E_PHY_TYPE_25GBASE_CR		= 0x20,
>   	I40E_PHY_TYPE_25GBASE_SR		= 0x21,
>   	I40E_PHY_TYPE_25GBASE_LR		= 0x22,
> +	I40E_PHY_TYPE_EMPTY			= 0xFE,
> +	I40E_PHY_TYPE_DEFAULT			= 0xFF,
>   	I40E_PHY_TYPE_MAX
>   };
>   
> @@ -1942,19 +1946,31 @@ struct i40e_aqc_get_link_status {
>   #define I40E_AQ_25G_SERDES_UCODE_ERR	0X04
>   #define I40E_AQ_25G_NIMB_UCODE_ERR	0X05
>   	u8	loopback; /* use defines from i40e_aqc_set_lb_mode */
> +/* Since firmware API 1.7 loopback field keeps power class info as well */
> +#define I40E_AQ_LOOPBACK_MASK		0x07
> +#define I40E_AQ_PWR_CLASS_SHIFT_LB	6
> +#define I40E_AQ_PWR_CLASS_MASK_LB	(0x03 << I40E_AQ_PWR_CLASS_SHIFT_LB)
>   	__le16	max_frame_size;
>   	u8	config;
>   #define I40E_AQ_CONFIG_FEC_KR_ENA	0x01
>   #define I40E_AQ_CONFIG_FEC_RS_ENA	0x02
>   #define I40E_AQ_CONFIG_CRC_ENA		0x04
>   #define I40E_AQ_CONFIG_PACING_MASK	0x78
> -	u8	power_desc;
> +	union {
> +		struct {
> +			u8	power_desc;
>   #define I40E_AQ_LINK_POWER_CLASS_1	0x00
>   #define I40E_AQ_LINK_POWER_CLASS_2	0x01
>   #define I40E_AQ_LINK_POWER_CLASS_3	0x02
>   #define I40E_AQ_LINK_POWER_CLASS_4	0x03
>   #define I40E_AQ_PWR_CLASS_MASK		0x03
> -	u8	reserved[4];
> +			u8	reserved[4];
> +		};
> +		struct {
> +			u8	link_type[4];

Wait, is this a 32-bit value on an odd-byte alignment?  No, no, no... we 
worked hard early on to not let the HW folks do this.

> +			u8	link_type_ext;
> +		};
> +	};
>   };
>   
>   I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
> index e9f30b8..c0aeda7 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_common.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
> @@ -1826,7 +1826,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
>   	hw_link_info->fec_info = resp->config & (I40E_AQ_CONFIG_FEC_KR_ENA |
>   						 I40E_AQ_CONFIG_FEC_RS_ENA);
>   	hw_link_info->ext_info = resp->ext_info;
> -	hw_link_info->loopback = resp->loopback;
> +	hw_link_info->loopback = resp->loopback & I40E_AQ_LOOPBACK_MASK;
>   	hw_link_info->max_frame_size = le16_to_cpu(resp->max_frame_size);
>   	hw_link_info->pacing = resp->config & I40E_AQ_CONFIG_PACING_MASK;
>   
> @@ -1857,6 +1857,12 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
>   	     hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)
>   		hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU;
>   
> +	if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
> +	    hw->aq.api_min_ver >= 7) {
> +		hw->phy.phy_types = le32_to_cpu(*(__le32 *)resp->link_type);

Reading a 32-bit word from an odd byte boundary will cause a non-x86 
machine (e.g. SPARC) a bit of heartburn, kernel log messages, and 
possibly a few customer complaints.  You're going to need a memcpy() to 
get it out of the funky memory address, then you can add in the byteswap.

		u32 tmp;
		memcpy(&tmp, &resp->link_type, sizeof(tmp));
		hw->phy.phy_types = le32_to_cpu(tmp);


> +		hw->phy.phy_types |= ((u64)resp->link_type_ext << 32);
> +	}
> +
>   	/* save link status information */
>   	if (link)
>   		*link = *hw_link_info;
> diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> index f9f48d1..709d114 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> @@ -1730,6 +1730,8 @@ enum i40e_aq_phy_type {
>   	I40E_PHY_TYPE_10GBASE_CR1_CU		= 0xB,
>   	I40E_PHY_TYPE_10GBASE_AOC		= 0xC,
>   	I40E_PHY_TYPE_40GBASE_AOC		= 0xD,
> +	I40E_PHY_TYPE_UNRECOGNIZED		= 0xE,
> +	I40E_PHY_TYPE_UNSUPPORTED		= 0xF,
>   	I40E_PHY_TYPE_100BASE_TX		= 0x11,
>   	I40E_PHY_TYPE_1000BASE_T		= 0x12,
>   	I40E_PHY_TYPE_10GBASE_T			= 0x13,
> @@ -1748,6 +1750,8 @@ enum i40e_aq_phy_type {
>   	I40E_PHY_TYPE_25GBASE_CR		= 0x20,
>   	I40E_PHY_TYPE_25GBASE_SR		= 0x21,
>   	I40E_PHY_TYPE_25GBASE_LR		= 0x22,
> +	I40E_PHY_TYPE_EMPTY			= 0xFE,
> +	I40E_PHY_TYPE_DEFAULT			= 0xFF,
>   	I40E_PHY_TYPE_MAX
>   };
>   
> @@ -1938,19 +1942,31 @@ struct i40e_aqc_get_link_status {
>   #define I40E_AQ_25G_SERDES_UCODE_ERR	0X04
>   #define I40E_AQ_25G_NIMB_UCODE_ERR	0X05
>   	u8	loopback; /* use defines from i40e_aqc_set_lb_mode */
> +/* Since firmware API 1.7 loopback field keeps power class info as well */
> +#define I40E_AQ_LOOPBACK_MASK		0x07
> +#define I40E_AQ_PWR_CLASS_SHIFT_LB	6
> +#define I40E_AQ_PWR_CLASS_MASK_LB	(0x03 << I40E_AQ_PWR_CLASS_SHIFT_LB)
>   	__le16	max_frame_size;
>   	u8	config;
>   #define I40E_AQ_CONFIG_FEC_KR_ENA	0x01
>   #define I40E_AQ_CONFIG_FEC_RS_ENA	0x02
>   #define I40E_AQ_CONFIG_CRC_ENA		0x04
>   #define I40E_AQ_CONFIG_PACING_MASK	0x78
> -	u8	power_desc;
> +	union {
> +		struct {
> +			u8	power_desc;
>   #define I40E_AQ_LINK_POWER_CLASS_1	0x00
>   #define I40E_AQ_LINK_POWER_CLASS_2	0x01
>   #define I40E_AQ_LINK_POWER_CLASS_3	0x02
>   #define I40E_AQ_LINK_POWER_CLASS_4	0x03
>   #define I40E_AQ_PWR_CLASS_MASK		0x03
> -	u8	reserved[4];
> +			u8	reserved[4];
> +		};
> +		struct {
> +			u8	link_type[4];
> +			u8	link_type_ext;
> +		};
> +	};
>   };
>   
>   I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
> 


More information about the Intel-wired-lan mailing list