diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_common.c')
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_common.c | 118 | 
1 files changed, 95 insertions, 23 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 7560f06768e0..d4055037af89 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -29,6 +29,7 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw)  		case I40E_DEV_ID_QSFP_C:  		case I40E_DEV_ID_10G_BASE_T:  		case I40E_DEV_ID_10G_BASE_T4: +		case I40E_DEV_ID_10G_BASE_T_BC:  		case I40E_DEV_ID_10G_B:  		case I40E_DEV_ID_10G_SFP:  		case I40E_DEV_ID_20G_KR2: @@ -933,10 +934,6 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw)  	else  		hw->pf_id = (u8)(func_rid & 0x7); -	if (hw->mac.type == I40E_MAC_X722) -		hw->flags |= I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE | -			     I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK; -  	status = i40e_init_nvm(hw);  	return status;  } @@ -1441,9 +1438,9 @@ static u32 i40e_led_is_mine(struct i40e_hw *hw, int idx)  	u32 gpio_val = 0;  	u32 port; -	if (!hw->func_caps.led[idx]) +	if (!I40E_IS_X710TL_DEVICE(hw->device_id) && +	    !hw->func_caps.led[idx])  		return 0; -  	gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(idx));  	port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) >>  		I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT; @@ -1462,8 +1459,15 @@ static u32 i40e_led_is_mine(struct i40e_hw *hw, int idx)  #define I40E_FILTER_ACTIVITY 0xE  #define I40E_LINK_ACTIVITY 0xC  #define I40E_MAC_ACTIVITY 0xD +#define I40E_FW_LED BIT(4) +#define I40E_LED_MODE_VALID (I40E_GLGEN_GPIO_CTL_LED_MODE_MASK >> \ +			     I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) +  #define I40E_LED0 22 +#define I40E_PIN_FUNC_SDP 0x0 +#define I40E_PIN_FUNC_LED 0x1 +  /**   * i40e_led_get - return current on/off mode   * @hw: pointer to the hw struct @@ -1508,8 +1512,10 @@ void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink)  {  	int i; -	if (mode & 0xfffffff0) +	if (mode & ~I40E_LED_MODE_VALID) {  		hw_dbg(hw, "invalid mode passed in %X\n", mode); +		return; +	}  	/* as per the documentation GPIO 22-29 are the LED  	 * GPIO pins named LED0..LED7 @@ -1519,6 +1525,20 @@ void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink)  		if (!gpio_val)  			continue; + +		if (I40E_IS_X710TL_DEVICE(hw->device_id)) { +			u32 pin_func = 0; + +			if (mode & I40E_FW_LED) +				pin_func = I40E_PIN_FUNC_SDP; +			else +				pin_func = I40E_PIN_FUNC_LED; + +			gpio_val &= ~I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK; +			gpio_val |= ((pin_func << +				     I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT) & +				     I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK); +		}  		gpio_val &= ~I40E_GLGEN_GPIO_CTL_LED_MODE_MASK;  		/* this & is a bit of paranoia, but serves as a range check */  		gpio_val |= ((mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) & @@ -2571,9 +2591,16 @@ noinline_for_stack i40e_status i40e_update_link_info(struct i40e_hw *hw)  		if (status)  			return status; -		hw->phy.link_info.req_fec_info = -			abilities.fec_cfg_curr_mod_ext_info & -			(I40E_AQ_REQUEST_FEC_KR | I40E_AQ_REQUEST_FEC_RS); +		if (abilities.fec_cfg_curr_mod_ext_info & +		    I40E_AQ_ENABLE_FEC_AUTO) +			hw->phy.link_info.req_fec_info = +				(I40E_AQ_REQUEST_FEC_KR | +				 I40E_AQ_REQUEST_FEC_RS); +		else +			hw->phy.link_info.req_fec_info = +				abilities.fec_cfg_curr_mod_ext_info & +				(I40E_AQ_REQUEST_FEC_KR | +				 I40E_AQ_REQUEST_FEC_RS);  		memcpy(hw->phy.link_info.module_type, &abilities.module_type,  		       sizeof(hw->phy.link_info.module_type)); @@ -4885,6 +4912,7 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw,  		break;  	case I40E_DEV_ID_10G_BASE_T:  	case I40E_DEV_ID_10G_BASE_T4: +	case I40E_DEV_ID_10G_BASE_T_BC:  	case I40E_DEV_ID_10G_BASE_T_X722:  	case I40E_DEV_ID_25G_B:  	case I40E_DEV_ID_25G_SFP28: @@ -5044,7 +5072,7 @@ static enum i40e_status_code i40e_led_get_reg(struct i40e_hw *hw, u16 led_addr,  		status =  		       i40e_aq_get_phy_register(hw,  						I40E_AQ_PHY_REG_ACCESS_EXTERNAL, -						I40E_PHY_COM_REG_PAGE, +						I40E_PHY_COM_REG_PAGE, true,  						I40E_PHY_LED_PROV_REG_1,  						reg_val, NULL);  	} else { @@ -5077,7 +5105,7 @@ static enum i40e_status_code i40e_led_set_reg(struct i40e_hw *hw, u16 led_addr,  		status =  		       i40e_aq_set_phy_register(hw,  						I40E_AQ_PHY_REG_ACCESS_EXTERNAL, -						I40E_PHY_COM_REG_PAGE, +						I40E_PHY_COM_REG_PAGE, true,  						I40E_PHY_LED_PROV_REG_1,  						reg_val, NULL);  	} else { @@ -5116,7 +5144,7 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,  		status =  		      i40e_aq_get_phy_register(hw,  					       I40E_AQ_PHY_REG_ACCESS_EXTERNAL, -					       I40E_PHY_COM_REG_PAGE, +					       I40E_PHY_COM_REG_PAGE, true,  					       I40E_PHY_LED_PROV_REG_1,  					       ®_val_aq, NULL);  		if (status == I40E_SUCCESS) @@ -5321,20 +5349,49 @@ do_retry:  }  /** - * i40e_aq_set_phy_register + * i40e_mdio_if_number_selection - MDIO I/F number selection + * @hw: pointer to the hw struct + * @set_mdio: use MDIO I/F number specified by mdio_num + * @mdio_num: MDIO I/F number + * @cmd: pointer to PHY Register command structure + **/ +static void i40e_mdio_if_number_selection(struct i40e_hw *hw, bool set_mdio, +					  u8 mdio_num, +					  struct i40e_aqc_phy_register_access *cmd) +{ +	if (set_mdio && cmd->phy_interface == I40E_AQ_PHY_REG_ACCESS_EXTERNAL) { +		if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_EXTENDED) +			cmd->cmd_flags |= +				I40E_AQ_PHY_REG_ACCESS_SET_MDIO_IF_NUMBER | +				((mdio_num << +				I40E_AQ_PHY_REG_ACCESS_MDIO_IF_NUMBER_SHIFT) & +				I40E_AQ_PHY_REG_ACCESS_MDIO_IF_NUMBER_MASK); +		else +			i40e_debug(hw, I40E_DEBUG_PHY, +				   "MDIO I/F number selection not supported by current FW version.\n"); +	} +} + +/** + * i40e_aq_set_phy_register_ext   * @hw: pointer to the hw struct   * @phy_select: select which phy should be accessed   * @dev_addr: PHY device address + * @set_mdio: use MDIO I/F number specified by mdio_num + * @mdio_num: MDIO I/F number   * @reg_addr: PHY register address   * @reg_val: new register value   * @cmd_details: pointer to command details structure or NULL   *   * Write the external PHY register. + * NOTE: In common cases MDIO I/F number should not be changed, thats why you + * may use simple wrapper i40e_aq_set_phy_register.   **/ -i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw, -				     u8 phy_select, u8 dev_addr, -				     u32 reg_addr, u32 reg_val, -				     struct i40e_asq_cmd_details *cmd_details) +enum i40e_status_code i40e_aq_set_phy_register_ext(struct i40e_hw *hw, +			     u8 phy_select, u8 dev_addr, bool page_change, +			     bool set_mdio, u8 mdio_num, +			     u32 reg_addr, u32 reg_val, +			     struct i40e_asq_cmd_details *cmd_details)  {  	struct i40e_aq_desc desc;  	struct i40e_aqc_phy_register_access *cmd = @@ -5349,26 +5406,36 @@ i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw,  	cmd->reg_address = cpu_to_le32(reg_addr);  	cmd->reg_value = cpu_to_le32(reg_val); +	i40e_mdio_if_number_selection(hw, set_mdio, mdio_num, cmd); + +	if (!page_change) +		cmd->cmd_flags = I40E_AQ_PHY_REG_ACCESS_DONT_CHANGE_QSFP_PAGE; +  	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);  	return status;  }  /** - * i40e_aq_get_phy_register + * i40e_aq_get_phy_register_ext   * @hw: pointer to the hw struct   * @phy_select: select which phy should be accessed   * @dev_addr: PHY device address + * @set_mdio: use MDIO I/F number specified by mdio_num + * @mdio_num: MDIO I/F number   * @reg_addr: PHY register address   * @reg_val: read register value   * @cmd_details: pointer to command details structure or NULL   *   * Read the external PHY register. + * NOTE: In common cases MDIO I/F number should not be changed, thats why you + * may use simple wrapper i40e_aq_get_phy_register.   **/ -i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw, -				     u8 phy_select, u8 dev_addr, -				     u32 reg_addr, u32 *reg_val, -				     struct i40e_asq_cmd_details *cmd_details) +enum i40e_status_code i40e_aq_get_phy_register_ext(struct i40e_hw *hw, +			     u8 phy_select, u8 dev_addr, bool page_change, +			     bool set_mdio, u8 mdio_num, +			     u32 reg_addr, u32 *reg_val, +			     struct i40e_asq_cmd_details *cmd_details)  {  	struct i40e_aq_desc desc;  	struct i40e_aqc_phy_register_access *cmd = @@ -5382,6 +5449,11 @@ i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw,  	cmd->dev_address = dev_addr;  	cmd->reg_address = cpu_to_le32(reg_addr); +	i40e_mdio_if_number_selection(hw, set_mdio, mdio_num, cmd); + +	if (!page_change) +		cmd->cmd_flags = I40E_AQ_PHY_REG_ACCESS_DONT_CHANGE_QSFP_PAGE; +  	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);  	if (!status)  		*reg_val = le32_to_cpu(cmd->reg_value);  |