Commit 4efac6ff authored by David S. Miller's avatar David S. Miller

Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Jeff Kirsher says:

====================
40GbE Intel Wired LAN Driver Updates 2017-10-02

This series contains updates to i40e and i40evf.

Shannon Nelson fixes an issue where when a machine has more CPUs than
queue pairs, the counting gets a "little funky" and turns off Flow
Director.  So to correct it, limit the number of LAN queues initially
allocated to be sure there are some left for Flow Director and other
features.

Lihong cleans up dead code by removing a condition check which cannot
ever be true.

Christophe Jaillet fixes a potential NULL pointer dereference, which
could happen if kzalloc() fails.

Filip corrects the reporting of supported link modes, which was incorrect
for some NICs.  Added support for 'ethtool -m' command, which displays
information about QSFP+ modules.

Mariusz adds functions to read/write the LED registers to control the
LEDS, instead of accessing the registers directly whenever the LEDs
need to be controlled.

Jake fixes a regression where we introduced a scheduling while atomic,
so introduce a separate helper function which will manage its own need
for the mac_filter_hash_lock.  Also cleaned up the "PF" parameter in
i40e_vc_disable_vf() since it is never used and is not needed.  Fixed
a rare case where it is possible that a reset does not occur when
i40e_vc_disable_vf() is called, so modify i40e_reset_vf() to return a
bool to indicate whether it reset or not so that i40e_vc_disable_vf()
can wait until a reset actually occurs.

Alan adds the ability for the VF to request more or less underlying
allocated queues from the PF.  Fixes the incorrect method for clearing
the vf_states variable with a NULL assignment, when we should be
using atomic bitops since we don't actually want to clear all the
flags.  Fixed a resource leak, where the PF driver fails to inform
clients of a VF reset because we were incorrectly checking the
I40E_VF_STATE_PRE_ENABLE bit.

Mitch converts i40evf_map_rings_to_vectors() to a void function since
it cannot fail and allows us to clean up the checks for the function
return value.

Scott enables the driver(s) to pass traffic with VLAN tags using the
802.1ad Ethernet protocol.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d9601be1 ab243ec9
...@@ -607,6 +607,18 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw) ...@@ -607,6 +607,18 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
&oem_lo); &oem_lo);
hw->nvm.oem_ver = ((u32)oem_hi << 16) | oem_lo; hw->nvm.oem_ver = ((u32)oem_hi << 16) | oem_lo;
if (hw->mac.type == I40E_MAC_XL710 &&
hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
hw->aq.api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710) {
hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
}
/* The ability to RX (not drop) 802.1ad frames was added in API 1.7 */
if (hw->aq.api_maj_ver > 1 ||
(hw->aq.api_maj_ver == 1 &&
hw->aq.api_min_ver >= 7))
hw->flags |= I40E_HW_FLAG_802_1AD_CAPABLE;
if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) { if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) {
ret_code = I40E_ERR_FIRMWARE_API_VERSION; ret_code = I40E_ERR_FIRMWARE_API_VERSION;
goto init_adminq_free_arq; goto init_adminq_free_arq;
......
...@@ -244,6 +244,8 @@ enum i40e_admin_queue_opc { ...@@ -244,6 +244,8 @@ enum i40e_admin_queue_opc {
i40e_aqc_opc_set_phy_debug = 0x0622, i40e_aqc_opc_set_phy_debug = 0x0622,
i40e_aqc_opc_upload_ext_phy_fm = 0x0625, i40e_aqc_opc_upload_ext_phy_fm = 0x0625,
i40e_aqc_opc_run_phy_activity = 0x0626, i40e_aqc_opc_run_phy_activity = 0x0626,
i40e_aqc_opc_set_phy_register = 0x0628,
i40e_aqc_opc_get_phy_register = 0x0629,
/* NVM commands */ /* NVM commands */
i40e_aqc_opc_nvm_read = 0x0701, i40e_aqc_opc_nvm_read = 0x0701,
...@@ -773,7 +775,22 @@ struct i40e_aqc_set_switch_config { ...@@ -773,7 +775,22 @@ struct i40e_aqc_set_switch_config {
#define I40E_AQ_SET_SWITCH_CFG_PROMISC 0x0001 #define I40E_AQ_SET_SWITCH_CFG_PROMISC 0x0001
#define I40E_AQ_SET_SWITCH_CFG_L2_FILTER 0x0002 #define I40E_AQ_SET_SWITCH_CFG_L2_FILTER 0x0002
__le16 valid_flags; __le16 valid_flags;
u8 reserved[12]; /* The ethertype in switch_tag is dropped on ingress and used
* internally by the switch. Set this to zero for the default
* of 0x88a8 (802.1ad). Should be zero for firmware API
* versions lower than 1.7.
*/
__le16 switch_tag;
/* The ethertypes in first_tag and second_tag are used to
* match the outer and inner VLAN tags (respectively) when HW
* double VLAN tagging is enabled via the set port parameters
* AQ command. Otherwise these are both ignored. Set them to
* zero for their defaults of 0x8100 (802.1Q). Should be zero
* for firmware API versions lower than 1.7.
*/
__le16 first_tag;
__le16 second_tag;
u8 reserved[6];
}; };
I40E_CHECK_CMD_LENGTH(i40e_aqc_set_switch_config); I40E_CHECK_CMD_LENGTH(i40e_aqc_set_switch_config);
...@@ -1734,6 +1751,8 @@ enum i40e_aq_phy_type { ...@@ -1734,6 +1751,8 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_10GBASE_CR1_CU = 0xB, I40E_PHY_TYPE_10GBASE_CR1_CU = 0xB,
I40E_PHY_TYPE_10GBASE_AOC = 0xC, I40E_PHY_TYPE_10GBASE_AOC = 0xC,
I40E_PHY_TYPE_40GBASE_AOC = 0xD, 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_100BASE_TX = 0x11,
I40E_PHY_TYPE_1000BASE_T = 0x12, I40E_PHY_TYPE_1000BASE_T = 0x12,
I40E_PHY_TYPE_10GBASE_T = 0x13, I40E_PHY_TYPE_10GBASE_T = 0x13,
...@@ -1752,6 +1771,8 @@ enum i40e_aq_phy_type { ...@@ -1752,6 +1771,8 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_25GBASE_CR = 0x20, I40E_PHY_TYPE_25GBASE_CR = 0x20,
I40E_PHY_TYPE_25GBASE_SR = 0x21, I40E_PHY_TYPE_25GBASE_SR = 0x21,
I40E_PHY_TYPE_25GBASE_LR = 0x22, I40E_PHY_TYPE_25GBASE_LR = 0x22,
I40E_PHY_TYPE_EMPTY = 0xFE,
I40E_PHY_TYPE_DEFAULT = 0xFF,
I40E_PHY_TYPE_MAX I40E_PHY_TYPE_MAX
}; };
...@@ -1942,19 +1963,31 @@ struct i40e_aqc_get_link_status { ...@@ -1942,19 +1963,31 @@ struct i40e_aqc_get_link_status {
#define I40E_AQ_25G_SERDES_UCODE_ERR 0X04 #define I40E_AQ_25G_SERDES_UCODE_ERR 0X04
#define I40E_AQ_25G_NIMB_UCODE_ERR 0X05 #define I40E_AQ_25G_NIMB_UCODE_ERR 0X05
u8 loopback; /* use defines from i40e_aqc_set_lb_mode */ 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; __le16 max_frame_size;
u8 config; u8 config;
#define I40E_AQ_CONFIG_FEC_KR_ENA 0x01 #define I40E_AQ_CONFIG_FEC_KR_ENA 0x01
#define I40E_AQ_CONFIG_FEC_RS_ENA 0x02 #define I40E_AQ_CONFIG_FEC_RS_ENA 0x02
#define I40E_AQ_CONFIG_CRC_ENA 0x04 #define I40E_AQ_CONFIG_CRC_ENA 0x04
#define I40E_AQ_CONFIG_PACING_MASK 0x78 #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_1 0x00
#define I40E_AQ_LINK_POWER_CLASS_2 0x01 #define I40E_AQ_LINK_POWER_CLASS_2 0x01
#define I40E_AQ_LINK_POWER_CLASS_3 0x02 #define I40E_AQ_LINK_POWER_CLASS_3 0x02
#define I40E_AQ_LINK_POWER_CLASS_4 0x03 #define I40E_AQ_LINK_POWER_CLASS_4 0x03
#define I40E_AQ_PWR_CLASS_MASK 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); I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
...@@ -2037,6 +2070,22 @@ struct i40e_aqc_run_phy_activity { ...@@ -2037,6 +2070,22 @@ struct i40e_aqc_run_phy_activity {
I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity); I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity);
/* Set PHY Register command (0x0628) */
/* Get PHY Register command (0x0629) */
struct i40e_aqc_phy_register_access {
u8 phy_interface;
#define I40E_AQ_PHY_REG_ACCESS_INTERNAL 0
#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL 1
#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE 2
u8 dev_address;
u8 reserved1[2];
__le32 reg_address;
__le32 reg_value;
u8 reserved2[4];
};
I40E_CHECK_CMD_LENGTH(i40e_aqc_phy_register_access);
/* NVM Read command (indirect 0x0701) /* NVM Read command (indirect 0x0701)
* NVM Erase commands (direct 0x0702) * NVM Erase commands (direct 0x0702)
* NVM Update commands (indirect 0x0703) * NVM Update commands (indirect 0x0703)
......
...@@ -1821,7 +1821,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw, ...@@ -1821,7 +1821,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 | hw_link_info->fec_info = resp->config & (I40E_AQ_CONFIG_FEC_KR_ENA |
I40E_AQ_CONFIG_FEC_RS_ENA); I40E_AQ_CONFIG_FEC_RS_ENA);
hw_link_info->ext_info = resp->ext_info; 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->max_frame_size = le16_to_cpu(resp->max_frame_size);
hw_link_info->pacing = resp->config & I40E_AQ_CONFIG_PACING_MASK; hw_link_info->pacing = resp->config & I40E_AQ_CONFIG_PACING_MASK;
...@@ -1852,6 +1852,15 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw, ...@@ -1852,6 +1852,15 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE) hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)
hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU; 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) {
__le32 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 */ /* save link status information */
if (link) if (link)
*link = *hw_link_info; *link = *hw_link_info;
...@@ -2393,7 +2402,11 @@ enum i40e_status_code i40e_aq_set_switch_config(struct i40e_hw *hw, ...@@ -2393,7 +2402,11 @@ enum i40e_status_code i40e_aq_set_switch_config(struct i40e_hw *hw,
i40e_aqc_opc_set_switch_config); i40e_aqc_opc_set_switch_config);
scfg->flags = cpu_to_le16(flags); scfg->flags = cpu_to_le16(flags);
scfg->valid_flags = cpu_to_le16(valid_flags); scfg->valid_flags = cpu_to_le16(valid_flags);
if (hw->flags & I40E_HW_FLAG_802_1AD_CAPABLE) {
scfg->switch_tag = cpu_to_le16(hw->switch_tag);
scfg->first_tag = cpu_to_le16(hw->first_tag);
scfg->second_tag = cpu_to_le16(hw->second_tag);
}
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
return status; return status;
...@@ -4827,6 +4840,74 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw, ...@@ -4827,6 +4840,74 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
return status; return status;
} }
/**
* i40e_led_get_reg - read LED register
* @hw: pointer to the HW structure
* @led_addr: LED register address
* @reg_val: read register value
**/
static enum i40e_status_code i40e_led_get_reg(struct i40e_hw *hw, u16 led_addr,
u32 *reg_val)
{
enum i40e_status_code status;
u8 phy_addr = 0;
u8 port_num;
u32 i;
*reg_val = 0;
if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
status =
i40e_aq_get_phy_register(hw,
I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
I40E_PHY_COM_REG_PAGE,
I40E_PHY_LED_PROV_REG_1,
reg_val, NULL);
} else {
i = rd32(hw, I40E_PFGEN_PORTNUM);
port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
phy_addr = i40e_get_phy_address(hw, port_num);
status = i40e_read_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr,
(u16 *)reg_val);
}
return status;
}
/**
* i40e_led_set_reg - write LED register
* @hw: pointer to the HW structure
* @led_addr: LED register address
* @reg_val: register value to write
**/
static enum i40e_status_code i40e_led_set_reg(struct i40e_hw *hw, u16 led_addr,
u32 reg_val)
{
enum i40e_status_code status;
u8 phy_addr = 0;
u8 port_num;
u32 i;
if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
status =
i40e_aq_set_phy_register(hw,
I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
I40E_PHY_COM_REG_PAGE,
I40E_PHY_LED_PROV_REG_1,
reg_val, NULL);
} else {
i = rd32(hw, I40E_PFGEN_PORTNUM);
port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
phy_addr = i40e_get_phy_address(hw, port_num);
status = i40e_write_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr,
(u16)reg_val);
}
return status;
}
/** /**
* i40e_led_get_phy - return current on/off mode * i40e_led_get_phy - return current on/off mode
* @hw: pointer to the hw struct * @hw: pointer to the hw struct
...@@ -4844,7 +4925,19 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr, ...@@ -4844,7 +4925,19 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
u16 temp_addr; u16 temp_addr;
u8 port_num; u8 port_num;
u32 i; u32 i;
u32 reg_val_aq;
if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
status =
i40e_aq_get_phy_register(hw,
I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
I40E_PHY_COM_REG_PAGE,
I40E_PHY_LED_PROV_REG_1,
&reg_val_aq, NULL);
if (status == I40E_SUCCESS)
*val = (u16)reg_val_aq;
return status;
}
temp_addr = I40E_PHY_LED_PROV_REG_1; temp_addr = I40E_PHY_LED_PROV_REG_1;
i = rd32(hw, I40E_PFGEN_PORTNUM); i = rd32(hw, I40E_PFGEN_PORTNUM);
port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK); port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
...@@ -4879,51 +4972,38 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on, ...@@ -4879,51 +4972,38 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on,
u16 led_addr, u32 mode) u16 led_addr, u32 mode)
{ {
i40e_status status = 0; i40e_status status = 0;
u16 led_ctl = 0; u32 led_ctl = 0;
u16 led_reg = 0; u32 led_reg = 0;
u8 phy_addr = 0;
u8 port_num;
u32 i;
i = rd32(hw, I40E_PFGEN_PORTNUM); status = i40e_led_get_reg(hw, led_addr, &led_reg);
port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
phy_addr = i40e_get_phy_address(hw, port_num);
status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, &led_reg);
if (status) if (status)
return status; return status;
led_ctl = led_reg; led_ctl = led_reg;
if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) { if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
led_reg = 0; led_reg = 0;
status = i40e_write_phy_register_clause45(hw, status = i40e_led_set_reg(hw, led_addr, led_reg);
I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr,
led_reg);
if (status) if (status)
return status; return status;
} }
status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE, status = i40e_led_get_reg(hw, led_addr, &led_reg);
led_addr, phy_addr, &led_reg);
if (status) if (status)
goto restore_config; goto restore_config;
if (on) if (on)
led_reg = I40E_PHY_LED_MANUAL_ON; led_reg = I40E_PHY_LED_MANUAL_ON;
else else
led_reg = 0; led_reg = 0;
status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_reg); status = i40e_led_set_reg(hw, led_addr, led_reg);
if (status) if (status)
goto restore_config; goto restore_config;
if (mode & I40E_PHY_LED_MODE_ORIG) { if (mode & I40E_PHY_LED_MODE_ORIG) {
led_ctl = (mode & I40E_PHY_LED_MODE_MASK); led_ctl = (mode & I40E_PHY_LED_MODE_MASK);
status = i40e_write_phy_register_clause45(hw, status = i40e_led_set_reg(hw, led_addr, led_ctl);
I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_ctl);
} }
return status; return status;
restore_config: restore_config:
status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE, status = i40e_led_set_reg(hw, led_addr, led_ctl);
led_addr, phy_addr, led_ctl);
return status; return status;
} }
...@@ -5053,6 +5133,75 @@ void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val) ...@@ -5053,6 +5133,75 @@ void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val)
wr32(hw, reg_addr, reg_val); wr32(hw, reg_addr, reg_val);
} }
/**
* i40e_aq_set_phy_register
* @hw: pointer to the hw struct
* @phy_select: select which phy should be accessed
* @dev_addr: PHY device address
* @reg_addr: PHY register address
* @reg_val: new register value
* @cmd_details: pointer to command details structure or NULL
*
* Write the external 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)
{
struct i40e_aq_desc desc;
struct i40e_aqc_phy_register_access *cmd =
(struct i40e_aqc_phy_register_access *)&desc.params.raw;
i40e_status status;
i40e_fill_default_direct_cmd_desc(&desc,
i40e_aqc_opc_set_phy_register);
cmd->phy_interface = phy_select;
cmd->dev_address = dev_addr;
cmd->reg_address = cpu_to_le32(reg_addr);
cmd->reg_value = cpu_to_le32(reg_val);
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
return status;
}
/**
* i40e_aq_get_phy_register
* @hw: pointer to the hw struct
* @phy_select: select which phy should be accessed
* @dev_addr: PHY device address
* @reg_addr: PHY register address
* @reg_val: read register value
* @cmd_details: pointer to command details structure or NULL
*
* Read the external 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)
{
struct i40e_aq_desc desc;
struct i40e_aqc_phy_register_access *cmd =
(struct i40e_aqc_phy_register_access *)&desc.params.raw;
i40e_status status;
i40e_fill_default_direct_cmd_desc(&desc,
i40e_aqc_opc_get_phy_register);
cmd->phy_interface = phy_select;
cmd->dev_address = dev_addr;
cmd->reg_address = cpu_to_le32(reg_addr);
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
if (!status)
*reg_val = le32_to_cpu(cmd->reg_value);
return status;
}
/** /**
* i40e_aq_write_ppp - Write pipeline personalization profile (ppp) * i40e_aq_write_ppp - Write pipeline personalization profile (ppp)
* @hw: pointer to the hw struct * @hw: pointer to the hw struct
......
...@@ -4196,6 +4196,158 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags) ...@@ -4196,6 +4196,158 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
return 0; return 0;
} }
/**
* i40e_get_module_info - get (Q)SFP+ module type info
* @netdev: network interface device structure
* @modinfo: module EEPROM size and layout information structure
**/
static int i40e_get_module_info(struct net_device *netdev,
struct ethtool_modinfo *modinfo)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
u32 sff8472_comp = 0;
u32 sff8472_swap = 0;
u32 sff8636_rev = 0;
i40e_status status;
u32 type = 0;
/* Check if firmware supports reading module EEPROM. */
if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
netdev_err(vsi->netdev, "Module EEPROM memory read not supported. Please update the NVM image.\n");
return -EINVAL;
}
status = i40e_update_link_info(hw);
if (status)
return -EIO;
if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
netdev_err(vsi->netdev, "Cannot read module EEPROM memory. No module connected.\n");
return -EINVAL;
}
type = hw->phy.link_info.module_type[0];
switch (type) {
case I40E_MODULE_TYPE_SFP:
status = i40e_aq_get_phy_register(hw,
I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
I40E_I2C_EEPROM_DEV_ADDR,
I40E_MODULE_SFF_8472_COMP,
&sff8472_comp, NULL);
if (status)
return -EIO;
status = i40e_aq_get_phy_register(hw,
I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
I40E_I2C_EEPROM_DEV_ADDR,
I40E_MODULE_SFF_8472_SWAP,
&sff8472_swap, NULL);
if (status)
return -EIO;
/* Check if the module requires address swap to access
* the other EEPROM memory page.
*/
if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
netdev_warn(vsi->netdev, "Module address swap to access page 0xA2 is not supported.\n");
modinfo->type = ETH_MODULE_SFF_8079;
modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
} else if (sff8472_comp == 0x00) {
/* Module is not SFF-8472 compliant */
modinfo->type = ETH_MODULE_SFF_8079;
modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
} else {
modinfo->type = ETH_MODULE_SFF_8472;
modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
}
break;
case I40E_MODULE_TYPE_QSFP_PLUS:
/* Read from memory page 0. */
status = i40e_aq_get_phy_register(hw,
I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
0,
I40E_MODULE_REVISION_ADDR,
&sff8636_rev, NULL);
if (status)
return -EIO;
/* Determine revision compliance byte */
if (sff8636_rev > 0x02) {
/* Module is SFF-8636 compliant */
modinfo->type = ETH_MODULE_SFF_8636;
modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
} else {
modinfo->type = ETH_MODULE_SFF_8436;
modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
}
break;
case I40E_MODULE_TYPE_QSFP28:
modinfo->type = ETH_MODULE_SFF_8636;
modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
break;
default:
netdev_err(vsi->netdev, "Module type unrecognized\n");
return -EINVAL;
}
return 0;
}
/**
* i40e_get_module_eeprom - fills buffer with (Q)SFP+ module memory contents
* @netdev: network interface device structure
* @ee: EEPROM dump request structure
* @data: buffer to be filled with EEPROM contents
**/
static int i40e_get_module_eeprom(struct net_device *netdev,
struct ethtool_eeprom *ee,
u8 *data)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
bool is_sfp = false;
i40e_status status;
u32 value = 0;
int i;
if (!ee || !ee->len || !data)
return -EINVAL;
if (hw->phy.link_info.module_type[0] == I40E_MODULE_TYPE_SFP)
is_sfp = true;
for (i = 0; i < ee->len; i++) {
u32 offset = i + ee->offset;
u32 addr = is_sfp ? I40E_I2C_EEPROM_DEV_ADDR : 0;
/* Check if we need to access the other memory page */
if (is_sfp) {
if (offset >= ETH_MODULE_SFF_8079_LEN) {
offset -= ETH_MODULE_SFF_8079_LEN;
addr = I40E_I2C_EEPROM_DEV_ADDR2;
}
} else {
while (offset >= ETH_MODULE_SFF_8436_LEN) {
/* Compute memory page number and offset. */
offset -= ETH_MODULE_SFF_8436_LEN / 2;
addr++;
}
}
status = i40e_aq_get_phy_register(hw,
I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
addr, offset, &value, NULL);
if (status)
return -EIO;
data[i] = value;
}
return 0;
}
static const struct ethtool_ops i40e_ethtool_ops = { static const struct ethtool_ops i40e_ethtool_ops = {
.get_drvinfo = i40e_get_drvinfo, .get_drvinfo = i40e_get_drvinfo,
.get_regs_len = i40e_get_regs_len, .get_regs_len = i40e_get_regs_len,
...@@ -4228,6 +4380,8 @@ static const struct ethtool_ops i40e_ethtool_ops = { ...@@ -4228,6 +4380,8 @@ static const struct ethtool_ops i40e_ethtool_ops = {
.set_rxfh = i40e_set_rxfh, .set_rxfh = i40e_set_rxfh,
.get_channels = i40e_get_channels, .get_channels = i40e_get_channels,
.set_channels = i40e_set_channels, .set_channels = i40e_set_channels,
.get_module_info = i40e_get_module_info,
.get_module_eeprom = i40e_get_module_eeprom,
.get_ts_info = i40e_get_ts_info, .get_ts_info = i40e_get_ts_info,
.get_priv_flags = i40e_get_priv_flags, .get_priv_flags = i40e_get_priv_flags,
.set_priv_flags = i40e_set_priv_flags, .set_priv_flags = i40e_set_priv_flags,
......
...@@ -11093,6 +11093,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) ...@@ -11093,6 +11093,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
static void i40e_determine_queue_usage(struct i40e_pf *pf) static void i40e_determine_queue_usage(struct i40e_pf *pf)
{ {
int queues_left; int queues_left;
int q_max;
pf->num_lan_qps = 0; pf->num_lan_qps = 0;
...@@ -11139,10 +11140,12 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) ...@@ -11139,10 +11140,12 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
I40E_FLAG_DCB_ENABLED); I40E_FLAG_DCB_ENABLED);
dev_info(&pf->pdev->dev, "not enough queues for DCB. DCB is disabled.\n"); dev_info(&pf->pdev->dev, "not enough queues for DCB. DCB is disabled.\n");
} }
pf->num_lan_qps = max_t(int, pf->rss_size_max,
num_online_cpus()); /* limit lan qps to the smaller of qps, cpus or msix */
pf->num_lan_qps = min_t(int, pf->num_lan_qps, q_max = max_t(int, pf->rss_size_max, num_online_cpus());
pf->hw.func_caps.num_tx_qp); q_max = min_t(int, q_max, pf->hw.func_caps.num_tx_qp);
q_max = min_t(int, q_max, pf->hw.func_caps.num_msix_vectors);
pf->num_lan_qps = q_max;
queues_left -= pf->num_lan_qps; queues_left -= pf->num_lan_qps;
} }
...@@ -11358,6 +11361,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -11358,6 +11361,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw->bus.bus_id = pdev->bus->number; hw->bus.bus_id = pdev->bus->number;
pf->instance = pfs_found; pf->instance = pfs_found;
/* Select something other than the 802.1ad ethertype for the
* switch to use internally and drop on ingress.
*/
hw->switch_tag = 0xffff;
hw->first_tag = ETH_P_8021AD;
hw->second_tag = ETH_P_8021Q;
INIT_LIST_HEAD(&pf->l3_flex_pit_list); INIT_LIST_HEAD(&pf->l3_flex_pit_list);
INIT_LIST_HEAD(&pf->l4_flex_pit_list); INIT_LIST_HEAD(&pf->l4_flex_pit_list);
......
...@@ -360,6 +360,15 @@ i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw, ...@@ -360,6 +360,15 @@ i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw,
u32 reg_addr, u32 reg_val, u32 reg_addr, u32 reg_val,
struct i40e_asq_cmd_details *cmd_details); struct i40e_asq_cmd_details *cmd_details);
void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val); void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
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);
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);
i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw, i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw,
u16 reg, u8 phy_addr, u16 *value); u16 reg, u8 phy_addr, u16 *value);
i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw, i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
......
...@@ -428,6 +428,18 @@ struct i40e_nvm_access { ...@@ -428,6 +428,18 @@ struct i40e_nvm_access {
u8 data[1]; u8 data[1];
}; };
/* (Q)SFP module access definitions */
#define I40E_I2C_EEPROM_DEV_ADDR 0xA0
#define I40E_I2C_EEPROM_DEV_ADDR2 0xA2
#define I40E_MODULE_TYPE_ADDR 0x00
#define I40E_MODULE_REVISION_ADDR 0x01
#define I40E_MODULE_SFF_8472_COMP 0x5E
#define I40E_MODULE_SFF_8472_SWAP 0x5C
#define I40E_MODULE_SFF_ADDR_MODE 0x04
#define I40E_MODULE_TYPE_QSFP_PLUS 0x0D
#define I40E_MODULE_TYPE_QSFP28 0x11
#define I40E_MODULE_QSFP_MAX_LEN 640
/* PCI bus types */ /* PCI bus types */
enum i40e_bus_type { enum i40e_bus_type {
i40e_bus_type_unknown = 0, i40e_bus_type_unknown = 0,
...@@ -598,8 +610,15 @@ struct i40e_hw { ...@@ -598,8 +610,15 @@ struct i40e_hw {
struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */ struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */
#define I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE BIT_ULL(0) #define I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE BIT_ULL(0)
#define I40E_HW_FLAG_802_1AD_CAPABLE BIT_ULL(1)
#define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE BIT_ULL(2)
u64 flags; u64 flags;
/* Used in set switch config AQ command */
u16 switch_tag;
u16 first_tag;
u16 second_tag;
/* debug mask */ /* debug mask */
u32 debug_mask; u32 debug_mask;
char err_str[16]; char err_str[16];
......
...@@ -154,15 +154,30 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf) ...@@ -154,15 +154,30 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
/** /**
* i40e_vc_disable_vf * i40e_vc_disable_vf
* @pf: pointer to the PF info
* @vf: pointer to the VF info * @vf: pointer to the VF info
* *
* Disable the VF through a SW reset * Disable the VF through a SW reset.
**/ **/
static inline void i40e_vc_disable_vf(struct i40e_pf *pf, struct i40e_vf *vf) static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
{ {
int i;
i40e_vc_notify_vf_reset(vf); i40e_vc_notify_vf_reset(vf);
i40e_reset_vf(vf, false);
/* We want to ensure that an actual reset occurs initiated after this
* function was called. However, we do not want to wait forever, so
* we'll give a reasonable time and print a message if we failed to
* ensure a reset.
*/
for (i = 0; i < 20; i++) {
if (i40e_reset_vf(vf, false))
return;
usleep_range(10000, 20000);
}
dev_warn(&vf->pf->pdev->dev,
"Failed to initiate reset for VF %d after 200 milliseconds\n",
vf->vf_id);
} }
/** /**
...@@ -423,6 +438,9 @@ static int i40e_config_iwarp_qvlist(struct i40e_vf *vf, ...@@ -423,6 +438,9 @@ static int i40e_config_iwarp_qvlist(struct i40e_vf *vf,
(sizeof(struct virtchnl_iwarp_qv_info) * (sizeof(struct virtchnl_iwarp_qv_info) *
(qvlist_info->num_vectors - 1)); (qvlist_info->num_vectors - 1));
vf->qvlist_info = kzalloc(size, GFP_KERNEL); vf->qvlist_info = kzalloc(size, GFP_KERNEL);
if (!vf->qvlist_info)
return -ENOMEM;
vf->qvlist_info->num_vectors = qvlist_info->num_vectors; vf->qvlist_info->num_vectors = qvlist_info->num_vectors;
msix_vf = pf->hw.func_caps.num_msix_vectors_vf; msix_vf = pf->hw.func_caps.num_msix_vectors_vf;
...@@ -861,7 +879,8 @@ static void i40e_free_vf_res(struct i40e_vf *vf) ...@@ -861,7 +879,8 @@ static void i40e_free_vf_res(struct i40e_vf *vf)
} }
/* reset some of the state variables keeping track of the resources */ /* reset some of the state variables keeping track of the resources */
vf->num_queue_pairs = 0; vf->num_queue_pairs = 0;
vf->vf_states = 0; clear_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states);
clear_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states);
} }
/** /**
...@@ -1031,8 +1050,8 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf) ...@@ -1031,8 +1050,8 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf)
set_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states); set_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states);
clear_bit(I40E_VF_STATE_DISABLED, &vf->vf_states); clear_bit(I40E_VF_STATE_DISABLED, &vf->vf_states);
/* Do not notify the client during VF init */ /* Do not notify the client during VF init */
if (test_and_clear_bit(I40E_VF_STATE_PRE_ENABLE, if (!test_and_clear_bit(I40E_VF_STATE_PRE_ENABLE,
&vf->vf_states)) &vf->vf_states))
i40e_notify_client_of_vf_reset(pf, abs_vf_id); i40e_notify_client_of_vf_reset(pf, abs_vf_id);
vf->num_vlan = 0; vf->num_vlan = 0;
} }
...@@ -1049,9 +1068,9 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf) ...@@ -1049,9 +1068,9 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf)
* @vf: pointer to the VF structure * @vf: pointer to the VF structure
* @flr: VFLR was issued or not * @flr: VFLR was issued or not
* *
* reset the VF * Returns true if the VF is reset, false otherwise.
**/ **/
void i40e_reset_vf(struct i40e_vf *vf, bool flr) bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
{ {
struct i40e_pf *pf = vf->pf; struct i40e_pf *pf = vf->pf;
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
...@@ -1059,9 +1078,11 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) ...@@ -1059,9 +1078,11 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
u32 reg; u32 reg;
int i; int i;
/* If VFs have been disabled, there is no need to reset */ /* If the VFs have been disabled, this means something else is
* resetting the VF, so we shouldn't continue.
*/
if (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
return; return false;
i40e_trigger_vf_reset(vf, flr); i40e_trigger_vf_reset(vf, flr);
...@@ -1098,6 +1119,8 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) ...@@ -1098,6 +1119,8 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
i40e_flush(hw); i40e_flush(hw);
clear_bit(__I40E_VF_DISABLE, pf->state); clear_bit(__I40E_VF_DISABLE, pf->state);
return true;
} }
/** /**
...@@ -1109,8 +1132,10 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) ...@@ -1109,8 +1132,10 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
* VF, then do all the waiting in one chunk, and finally finish restoring each * VF, then do all the waiting in one chunk, and finally finish restoring each
* VF after the wait. This is useful during PF routines which need to reset * VF after the wait. This is useful during PF routines which need to reset
* all VFs, as otherwise it must perform these resets in a serialized fashion. * all VFs, as otherwise it must perform these resets in a serialized fashion.
*
* Returns true if any VFs were reset, and false otherwise.
**/ **/
void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
{ {
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
struct i40e_vf *vf; struct i40e_vf *vf;
...@@ -1119,11 +1144,11 @@ void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) ...@@ -1119,11 +1144,11 @@ void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
/* If we don't have any VFs, then there is nothing to reset */ /* If we don't have any VFs, then there is nothing to reset */
if (!pf->num_alloc_vfs) if (!pf->num_alloc_vfs)
return; return false;
/* If VFs have been disabled, there is no need to reset */ /* If VFs have been disabled, there is no need to reset */
if (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
return; return false;
/* Begin reset on all VFs at once */ /* Begin reset on all VFs at once */
for (v = 0; v < pf->num_alloc_vfs; v++) for (v = 0; v < pf->num_alloc_vfs; v++)
...@@ -1198,6 +1223,8 @@ void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) ...@@ -1198,6 +1223,8 @@ void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
i40e_flush(hw); i40e_flush(hw);
clear_bit(__I40E_VF_DISABLE, pf->state); clear_bit(__I40E_VF_DISABLE, pf->state);
return true;
} }
/** /**
...@@ -1560,6 +1587,8 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) ...@@ -1560,6 +1587,8 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_IWARP)) { (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_IWARP)) {
vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_IWARP; vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_IWARP;
set_bit(I40E_VF_STATE_IWARPENA, &vf->vf_states); set_bit(I40E_VF_STATE_IWARPENA, &vf->vf_states);
} else {
clear_bit(I40E_VF_STATE_IWARPENA, &vf->vf_states);
} }
if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PF) { if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
...@@ -2915,13 +2944,41 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) ...@@ -2915,13 +2944,41 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
} }
/* Force the VF driver stop so it has to reload with new MAC address */ /* Force the VF driver stop so it has to reload with new MAC address */
i40e_vc_disable_vf(pf, vf); i40e_vc_disable_vf(vf);
dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n"); dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n");
error_param: error_param:
return ret; return ret;
} }
/**
* i40e_vsi_has_vlans - True if VSI has configured VLANs
* @vsi: pointer to the vsi
*
* Check if a VSI has configured any VLANs. False if we have a port VLAN or if
* we have no configured VLANs. Do not call while holding the
* mac_filter_hash_lock.
*/
static bool i40e_vsi_has_vlans(struct i40e_vsi *vsi)
{
bool have_vlans;
/* If we have a port VLAN, then the VSI cannot have any VLANs
* configured, as all MAC/VLAN filters will be assigned to the PVID.
*/
if (vsi->info.pvid)
return false;
/* Since we don't have a PVID, we know that if the device is in VLAN
* mode it must be because of a VLAN filter configured on this VSI.
*/
spin_lock_bh(&vsi->mac_filter_hash_lock);
have_vlans = i40e_is_vsi_in_vlan(vsi);
spin_unlock_bh(&vsi->mac_filter_hash_lock);
return have_vlans;
}
/** /**
* i40e_ndo_set_vf_port_vlan * i40e_ndo_set_vf_port_vlan
* @netdev: network interface device structure * @netdev: network interface device structure
...@@ -2974,10 +3031,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, ...@@ -2974,10 +3031,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
/* duplicate request, so just return success */ /* duplicate request, so just return success */
goto error_pvid; goto error_pvid;
/* Locked once because multiple functions below iterate list */ if (i40e_vsi_has_vlans(vsi)) {
spin_lock_bh(&vsi->mac_filter_hash_lock);
if (le16_to_cpu(vsi->info.pvid) == 0 && i40e_is_vsi_in_vlan(vsi)) {
dev_err(&pf->pdev->dev, dev_err(&pf->pdev->dev,
"VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n", "VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n",
vf_id); vf_id);
...@@ -2985,11 +3039,14 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, ...@@ -2985,11 +3039,14 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
* the right thing by reconfiguring his network correctly * the right thing by reconfiguring his network correctly
* and then reloading the VF driver. * and then reloading the VF driver.
*/ */
i40e_vc_disable_vf(pf, vf); i40e_vc_disable_vf(vf);
/* During reset the VF got a new VSI, so refresh the pointer. */ /* During reset the VF got a new VSI, so refresh the pointer. */
vsi = pf->vsi[vf->lan_vsi_idx]; vsi = pf->vsi[vf->lan_vsi_idx];
} }
/* Locked once because multiple functions below iterate list */
spin_lock_bh(&vsi->mac_filter_hash_lock);
/* Check for condition where there was already a port VLAN ID /* Check for condition where there was already a port VLAN ID
* filter set and now it is being deleted by setting it to zero. * filter set and now it is being deleted by setting it to zero.
* Additionally check for the condition where there was a port * Additionally check for the condition where there was a port
...@@ -3354,14 +3411,11 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting) ...@@ -3354,14 +3411,11 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting)
vf = &pf->vf[vf_id]; vf = &pf->vf[vf_id];
if (!vf)
return -EINVAL;
if (setting == vf->trusted) if (setting == vf->trusted)
goto out; goto out;
vf->trusted = setting; vf->trusted = setting;
i40e_vc_notify_vf_reset(vf); i40e_vc_disable_vf(vf);
i40e_reset_vf(vf, false);
dev_info(&pf->pdev->dev, "VF %u is now %strusted\n", dev_info(&pf->pdev->dev, "VF %u is now %strusted\n",
vf_id, setting ? "" : "un"); vf_id, setting ? "" : "un");
out: out:
......
...@@ -56,7 +56,6 @@ enum i40e_vf_states { ...@@ -56,7 +56,6 @@ enum i40e_vf_states {
I40E_VF_STATE_INIT = 0, I40E_VF_STATE_INIT = 0,
I40E_VF_STATE_ACTIVE, I40E_VF_STATE_ACTIVE,
I40E_VF_STATE_IWARPENA, I40E_VF_STATE_IWARPENA,
I40E_VF_STATE_FCOEENA,
I40E_VF_STATE_DISABLED, I40E_VF_STATE_DISABLED,
I40E_VF_STATE_MC_PROMISC, I40E_VF_STATE_MC_PROMISC,
I40E_VF_STATE_UC_PROMISC, I40E_VF_STATE_UC_PROMISC,
...@@ -122,8 +121,8 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs); ...@@ -122,8 +121,8 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs);
int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode, int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
u32 v_retval, u8 *msg, u16 msglen); u32 v_retval, u8 *msg, u16 msglen);
int i40e_vc_process_vflr_event(struct i40e_pf *pf); int i40e_vc_process_vflr_event(struct i40e_pf *pf);
void i40e_reset_vf(struct i40e_vf *vf, bool flr); bool i40e_reset_vf(struct i40e_vf *vf, bool flr);
void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr); bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr);
void i40e_vc_notify_vf_reset(struct i40e_vf *vf); void i40e_vc_notify_vf_reset(struct i40e_vf *vf);
/* VF configuration related iplink handlers */ /* VF configuration related iplink handlers */
......
...@@ -244,6 +244,8 @@ enum i40e_admin_queue_opc { ...@@ -244,6 +244,8 @@ enum i40e_admin_queue_opc {
i40e_aqc_opc_set_phy_debug = 0x0622, i40e_aqc_opc_set_phy_debug = 0x0622,
i40e_aqc_opc_upload_ext_phy_fm = 0x0625, i40e_aqc_opc_upload_ext_phy_fm = 0x0625,
i40e_aqc_opc_run_phy_activity = 0x0626, i40e_aqc_opc_run_phy_activity = 0x0626,
i40e_aqc_opc_set_phy_register = 0x0628,
i40e_aqc_opc_get_phy_register = 0x0629,
/* NVM commands */ /* NVM commands */
i40e_aqc_opc_nvm_read = 0x0701, i40e_aqc_opc_nvm_read = 0x0701,
...@@ -769,7 +771,22 @@ struct i40e_aqc_set_switch_config { ...@@ -769,7 +771,22 @@ struct i40e_aqc_set_switch_config {
#define I40E_AQ_SET_SWITCH_CFG_PROMISC 0x0001 #define I40E_AQ_SET_SWITCH_CFG_PROMISC 0x0001
#define I40E_AQ_SET_SWITCH_CFG_L2_FILTER 0x0002 #define I40E_AQ_SET_SWITCH_CFG_L2_FILTER 0x0002
__le16 valid_flags; __le16 valid_flags;
u8 reserved[12]; /* The ethertype in switch_tag is dropped on ingress and used
* internally by the switch. Set this to zero for the default
* of 0x88a8 (802.1ad). Should be zero for firmware API
* versions lower than 1.7.
*/
__le16 switch_tag;
/* The ethertypes in first_tag and second_tag are used to
* match the outer and inner VLAN tags (respectively) when HW
* double VLAN tagging is enabled via the set port parameters
* AQ command. Otherwise these are both ignored. Set them to
* zero for their defaults of 0x8100 (802.1Q). Should be zero
* for firmware API versions lower than 1.7.
*/
__le16 first_tag;
__le16 second_tag;
u8 reserved[6];
}; };
I40E_CHECK_CMD_LENGTH(i40e_aqc_set_switch_config); I40E_CHECK_CMD_LENGTH(i40e_aqc_set_switch_config);
...@@ -1730,6 +1747,8 @@ enum i40e_aq_phy_type { ...@@ -1730,6 +1747,8 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_10GBASE_CR1_CU = 0xB, I40E_PHY_TYPE_10GBASE_CR1_CU = 0xB,
I40E_PHY_TYPE_10GBASE_AOC = 0xC, I40E_PHY_TYPE_10GBASE_AOC = 0xC,
I40E_PHY_TYPE_40GBASE_AOC = 0xD, 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_100BASE_TX = 0x11,
I40E_PHY_TYPE_1000BASE_T = 0x12, I40E_PHY_TYPE_1000BASE_T = 0x12,
I40E_PHY_TYPE_10GBASE_T = 0x13, I40E_PHY_TYPE_10GBASE_T = 0x13,
...@@ -1748,6 +1767,8 @@ enum i40e_aq_phy_type { ...@@ -1748,6 +1767,8 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_25GBASE_CR = 0x20, I40E_PHY_TYPE_25GBASE_CR = 0x20,
I40E_PHY_TYPE_25GBASE_SR = 0x21, I40E_PHY_TYPE_25GBASE_SR = 0x21,
I40E_PHY_TYPE_25GBASE_LR = 0x22, I40E_PHY_TYPE_25GBASE_LR = 0x22,
I40E_PHY_TYPE_EMPTY = 0xFE,
I40E_PHY_TYPE_DEFAULT = 0xFF,
I40E_PHY_TYPE_MAX I40E_PHY_TYPE_MAX
}; };
...@@ -1938,19 +1959,31 @@ struct i40e_aqc_get_link_status { ...@@ -1938,19 +1959,31 @@ struct i40e_aqc_get_link_status {
#define I40E_AQ_25G_SERDES_UCODE_ERR 0X04 #define I40E_AQ_25G_SERDES_UCODE_ERR 0X04
#define I40E_AQ_25G_NIMB_UCODE_ERR 0X05 #define I40E_AQ_25G_NIMB_UCODE_ERR 0X05
u8 loopback; /* use defines from i40e_aqc_set_lb_mode */ 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; __le16 max_frame_size;
u8 config; u8 config;
#define I40E_AQ_CONFIG_FEC_KR_ENA 0x01 #define I40E_AQ_CONFIG_FEC_KR_ENA 0x01
#define I40E_AQ_CONFIG_FEC_RS_ENA 0x02 #define I40E_AQ_CONFIG_FEC_RS_ENA 0x02
#define I40E_AQ_CONFIG_CRC_ENA 0x04 #define I40E_AQ_CONFIG_CRC_ENA 0x04
#define I40E_AQ_CONFIG_PACING_MASK 0x78 #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_1 0x00
#define I40E_AQ_LINK_POWER_CLASS_2 0x01 #define I40E_AQ_LINK_POWER_CLASS_2 0x01
#define I40E_AQ_LINK_POWER_CLASS_3 0x02 #define I40E_AQ_LINK_POWER_CLASS_3 0x02
#define I40E_AQ_LINK_POWER_CLASS_4 0x03 #define I40E_AQ_LINK_POWER_CLASS_4 0x03
#define I40E_AQ_PWR_CLASS_MASK 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); I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
...@@ -2030,6 +2063,22 @@ struct i40e_aqc_run_phy_activity { ...@@ -2030,6 +2063,22 @@ struct i40e_aqc_run_phy_activity {
I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity); I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity);
/* Set PHY Register command (0x0628) */
/* Get PHY Register command (0x0629) */
struct i40e_aqc_phy_register_access {
u8 phy_interface;
#define I40E_AQ_PHY_REG_ACCESS_INTERNAL 0
#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL 1
#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE 2
u8 dev_address;
u8 reserved1[2];
__le32 reg_address;
__le32 reg_value;
u8 reserved2[4];
};
I40E_CHECK_CMD_LENGTH(i40e_aqc_phy_register_access);
/* NVM Read command (indirect 0x0701) /* NVM Read command (indirect 0x0701)
* NVM Erase commands (direct 0x0702) * NVM Erase commands (direct 0x0702)
* NVM Update commands (indirect 0x0703) * NVM Update commands (indirect 0x0703)
......
...@@ -1041,6 +1041,75 @@ void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val) ...@@ -1041,6 +1041,75 @@ void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val)
wr32(hw, reg_addr, reg_val); wr32(hw, reg_addr, reg_val);
} }
/**
* i40evf_aq_set_phy_register
* @hw: pointer to the hw struct
* @phy_select: select which phy should be accessed
* @dev_addr: PHY device address
* @reg_addr: PHY register address
* @reg_val: new register value
* @cmd_details: pointer to command details structure or NULL
*
* Reset the external PHY.
**/
i40e_status i40evf_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)
{
struct i40e_aq_desc desc;
struct i40e_aqc_phy_register_access *cmd =
(struct i40e_aqc_phy_register_access *)&desc.params.raw;
i40e_status status;
i40evf_fill_default_direct_cmd_desc(&desc,
i40e_aqc_opc_set_phy_register);
cmd->phy_interface = phy_select;
cmd->dev_address = dev_addr;
cmd->reg_address = cpu_to_le32(reg_addr);
cmd->reg_value = cpu_to_le32(reg_val);
status = i40evf_asq_send_command(hw, &desc, NULL, 0, cmd_details);
return status;
}
/**
* i40evf_aq_get_phy_register
* @hw: pointer to the hw struct
* @phy_select: select which phy should be accessed
* @dev_addr: PHY device address
* @reg_addr: PHY register address
* @reg_val: read register value
* @cmd_details: pointer to command details structure or NULL
*
* Reset the external PHY.
**/
i40e_status i40evf_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)
{
struct i40e_aq_desc desc;
struct i40e_aqc_phy_register_access *cmd =
(struct i40e_aqc_phy_register_access *)&desc.params.raw;
i40e_status status;
i40evf_fill_default_direct_cmd_desc(&desc,
i40e_aqc_opc_get_phy_register);
cmd->phy_interface = phy_select;
cmd->dev_address = dev_addr;
cmd->reg_address = cpu_to_le32(reg_addr);
status = i40evf_asq_send_command(hw, &desc, NULL, 0, cmd_details);
if (!status)
*reg_val = le32_to_cpu(cmd->reg_value);
return status;
}
/** /**
* i40e_aq_send_msg_to_pf * i40e_aq_send_msg_to_pf
* @hw: pointer to the hardware structure * @hw: pointer to the hardware structure
......
...@@ -111,6 +111,15 @@ i40e_status i40evf_aq_rx_ctl_write_register(struct i40e_hw *hw, ...@@ -111,6 +111,15 @@ i40e_status i40evf_aq_rx_ctl_write_register(struct i40e_hw *hw,
u32 reg_addr, u32 reg_val, u32 reg_addr, u32 reg_val,
struct i40e_asq_cmd_details *cmd_details); struct i40e_asq_cmd_details *cmd_details);
void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val); void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
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);
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);
i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page, i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page,
u16 reg, u8 phy_addr, u16 *value); u16 reg, u8 phy_addr, u16 *value);
i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page, i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,
......
...@@ -401,6 +401,18 @@ struct i40e_nvm_access { ...@@ -401,6 +401,18 @@ struct i40e_nvm_access {
u8 data[1]; u8 data[1];
}; };
/* (Q)SFP module access definitions */
#define I40E_I2C_EEPROM_DEV_ADDR 0xA0
#define I40E_I2C_EEPROM_DEV_ADDR2 0xA2
#define I40E_MODULE_TYPE_ADDR 0x00
#define I40E_MODULE_REVISION_ADDR 0x01
#define I40E_MODULE_SFF_8472_COMP 0x5E
#define I40E_MODULE_SFF_8472_SWAP 0x5C
#define I40E_MODULE_SFF_ADDR_MODE 0x04
#define I40E_MODULE_TYPE_QSFP_PLUS 0x0D
#define I40E_MODULE_TYPE_QSFP28 0x11
#define I40E_MODULE_QSFP_MAX_LEN 640
/* PCI bus types */ /* PCI bus types */
enum i40e_bus_type { enum i40e_bus_type {
i40e_bus_type_unknown = 0, i40e_bus_type_unknown = 0,
...@@ -556,11 +568,19 @@ struct i40e_hw { ...@@ -556,11 +568,19 @@ struct i40e_hw {
/* LLDP/DCBX Status */ /* LLDP/DCBX Status */
u16 dcbx_status; u16 dcbx_status;
#define I40E_HW_FLAG_802_1AD_CAPABLE BIT_ULL(1)
#define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE BIT_ULL(2)
/* DCBX info */ /* DCBX info */
struct i40e_dcbx_config local_dcbx_config; /* Oper/Local Cfg */ struct i40e_dcbx_config local_dcbx_config; /* Oper/Local Cfg */
struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */ struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */
struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */ struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */
/* Used in set switch config AQ command */
u16 switch_tag;
u16 first_tag;
u16 second_tag;
/* debug mask */ /* debug mask */
u32 debug_mask; u32 debug_mask;
char err_str[16]; char err_str[16];
......
...@@ -102,6 +102,7 @@ struct i40e_vsi { ...@@ -102,6 +102,7 @@ struct i40e_vsi {
#define I40E_TX_CTXTDESC(R, i) \ #define I40E_TX_CTXTDESC(R, i) \
(&(((struct i40e_tx_context_desc *)((R)->desc))[i])) (&(((struct i40e_tx_context_desc *)((R)->desc))[i]))
#define MAX_QUEUES 16 #define MAX_QUEUES 16
#define I40EVF_MAX_REQ_QUEUES 4
#define I40EVF_HKEY_ARRAY_SIZE ((I40E_VFQF_HKEY_MAX_INDEX + 1) * 4) #define I40EVF_HKEY_ARRAY_SIZE ((I40E_VFQF_HKEY_MAX_INDEX + 1) * 4)
#define I40EVF_HLUT_ARRAY_SIZE ((I40E_VFQF_HLUT_MAX_INDEX + 1) * 4) #define I40EVF_HLUT_ARRAY_SIZE ((I40E_VFQF_HLUT_MAX_INDEX + 1) * 4)
...@@ -200,6 +201,7 @@ struct i40evf_adapter { ...@@ -200,6 +201,7 @@ struct i40evf_adapter {
struct list_head vlan_filter_list; struct list_head vlan_filter_list;
char misc_vector_name[IFNAMSIZ + 9]; char misc_vector_name[IFNAMSIZ + 9];
int num_active_queues; int num_active_queues;
int num_req_queues;
/* TX */ /* TX */
struct i40e_ring *tx_rings; struct i40e_ring *tx_rings;
...@@ -235,6 +237,7 @@ struct i40evf_adapter { ...@@ -235,6 +237,7 @@ struct i40evf_adapter {
#define I40EVF_FLAG_PROMISC_ON BIT(18) #define I40EVF_FLAG_PROMISC_ON BIT(18)
#define I40EVF_FLAG_ALLMULTI_ON BIT(19) #define I40EVF_FLAG_ALLMULTI_ON BIT(19)
#define I40EVF_FLAG_LEGACY_RX BIT(20) #define I40EVF_FLAG_LEGACY_RX BIT(20)
#define I40EVF_FLAG_REINIT_ITR_NEEDED BIT(21)
/* duplicates for common code */ /* duplicates for common code */
#define I40E_FLAG_DCB_ENABLED 0 #define I40E_FLAG_DCB_ENABLED 0
#define I40E_FLAG_RX_CSUM_ENABLED I40EVF_FLAG_RX_CSUM_ENABLED #define I40E_FLAG_RX_CSUM_ENABLED I40EVF_FLAG_RX_CSUM_ENABLED
...@@ -349,6 +352,7 @@ void i40evf_deconfigure_queues(struct i40evf_adapter *adapter); ...@@ -349,6 +352,7 @@ void i40evf_deconfigure_queues(struct i40evf_adapter *adapter);
void i40evf_enable_queues(struct i40evf_adapter *adapter); void i40evf_enable_queues(struct i40evf_adapter *adapter);
void i40evf_disable_queues(struct i40evf_adapter *adapter); void i40evf_disable_queues(struct i40evf_adapter *adapter);
void i40evf_map_queues(struct i40evf_adapter *adapter); void i40evf_map_queues(struct i40evf_adapter *adapter);
int i40evf_request_queues(struct i40evf_adapter *adapter, int num);
void i40evf_add_ether_addrs(struct i40evf_adapter *adapter); void i40evf_add_ether_addrs(struct i40evf_adapter *adapter);
void i40evf_del_ether_addrs(struct i40evf_adapter *adapter); void i40evf_del_ether_addrs(struct i40evf_adapter *adapter);
void i40evf_add_vlans(struct i40evf_adapter *adapter); void i40evf_add_vlans(struct i40evf_adapter *adapter);
......
...@@ -669,7 +669,7 @@ static void i40evf_get_channels(struct net_device *netdev, ...@@ -669,7 +669,7 @@ static void i40evf_get_channels(struct net_device *netdev,
struct i40evf_adapter *adapter = netdev_priv(netdev); struct i40evf_adapter *adapter = netdev_priv(netdev);
/* Report maximum channels */ /* Report maximum channels */
ch->max_combined = adapter->num_active_queues; ch->max_combined = I40EVF_MAX_REQ_QUEUES;
ch->max_other = NONQ_VECS; ch->max_other = NONQ_VECS;
ch->other_count = NONQ_VECS; ch->other_count = NONQ_VECS;
...@@ -677,6 +677,41 @@ static void i40evf_get_channels(struct net_device *netdev, ...@@ -677,6 +677,41 @@ static void i40evf_get_channels(struct net_device *netdev,
ch->combined_count = adapter->num_active_queues; ch->combined_count = adapter->num_active_queues;
} }
/**
* i40evf_set_channels: set the new channel count
* @netdev: network interface device structure
* @ch: channel information structure
*
* Negotiate a new number of channels with the PF then do a reset. During
* reset we'll realloc queues and fix the RSS table. Returns 0 on success,
* negative on failure.
**/
static int i40evf_set_channels(struct net_device *netdev,
struct ethtool_channels *ch)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
int num_req = ch->combined_count;
if (num_req != adapter->num_active_queues &&
!(adapter->vf_res->vf_cap_flags &
VIRTCHNL_VF_OFFLOAD_REQ_QUEUES)) {
dev_info(&adapter->pdev->dev, "PF is not capable of queue negotiation.\n");
return -EINVAL;
}
/* All of these should have already been checked by ethtool before this
* even gets to us, but just to be sure.
*/
if (num_req <= 0 || num_req > I40EVF_MAX_REQ_QUEUES)
return -EINVAL;
if (ch->rx_count || ch->tx_count || ch->other_count != NONQ_VECS)
return -EINVAL;
adapter->num_req_queues = num_req;
return i40evf_request_queues(adapter, num_req);
}
/** /**
* i40evf_get_rxfh_key_size - get the RSS hash key size * i40evf_get_rxfh_key_size - get the RSS hash key size
* @netdev: network interface device structure * @netdev: network interface device structure
...@@ -785,6 +820,7 @@ static const struct ethtool_ops i40evf_ethtool_ops = { ...@@ -785,6 +820,7 @@ static const struct ethtool_ops i40evf_ethtool_ops = {
.get_rxfh = i40evf_get_rxfh, .get_rxfh = i40evf_get_rxfh,
.set_rxfh = i40evf_set_rxfh, .set_rxfh = i40evf_set_rxfh,
.get_channels = i40evf_get_channels, .get_channels = i40evf_get_channels,
.set_channels = i40evf_set_channels,
.get_rxfh_key_size = i40evf_get_rxfh_key_size, .get_rxfh_key_size = i40evf_get_rxfh_key_size,
.get_link_ksettings = i40evf_get_link_ksettings, .get_link_ksettings = i40evf_get_link_ksettings,
}; };
......
...@@ -430,12 +430,11 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx) ...@@ -430,12 +430,11 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx)
* group the rings as "efficiently" as possible. You would add new * group the rings as "efficiently" as possible. You would add new
* mapping configurations in here. * mapping configurations in here.
**/ **/
static int i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter) static void i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter)
{ {
int rings_remaining = adapter->num_active_queues; int rings_remaining = adapter->num_active_queues;
int ridx = 0, vidx = 0; int ridx = 0, vidx = 0;
int q_vectors; int q_vectors;
int err = 0;
q_vectors = adapter->num_msix_vectors - NONQ_VECS; q_vectors = adapter->num_msix_vectors - NONQ_VECS;
...@@ -451,8 +450,6 @@ static int i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter) ...@@ -451,8 +450,6 @@ static int i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter)
} }
adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS; adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
return err;
} }
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
...@@ -1189,9 +1186,18 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter) ...@@ -1189,9 +1186,18 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter)
{ {
int i, num_active_queues; int i, num_active_queues;
num_active_queues = min_t(int, /* If we're in reset reallocating queues we don't actually know yet for
adapter->vsi_res->num_queue_pairs, * certain the PF gave us the number of queues we asked for but we'll
(int)(num_online_cpus())); * assume it did. Once basic reset is finished we'll confirm once we
* start negotiating config with PF.
*/
if (adapter->num_req_queues)
num_active_queues = adapter->num_req_queues;
else
num_active_queues = min_t(int,
adapter->vsi_res->num_queue_pairs,
(int)(num_online_cpus()));
adapter->tx_rings = kcalloc(num_active_queues, adapter->tx_rings = kcalloc(num_active_queues,
sizeof(struct i40e_ring), GFP_KERNEL); sizeof(struct i40e_ring), GFP_KERNEL);
...@@ -1539,6 +1545,46 @@ static void i40evf_free_rss(struct i40evf_adapter *adapter) ...@@ -1539,6 +1545,46 @@ static void i40evf_free_rss(struct i40evf_adapter *adapter)
adapter->rss_lut = NULL; adapter->rss_lut = NULL;
} }
/**
* i40evf_reinit_interrupt_scheme - Reallocate queues and vectors
* @adapter: board private structure
*
* Returns 0 on success, negative on failure
**/
static int i40evf_reinit_interrupt_scheme(struct i40evf_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
int err;
if (netif_running(netdev))
i40evf_free_traffic_irqs(adapter);
i40evf_free_misc_irq(adapter);
i40evf_reset_interrupt_capability(adapter);
i40evf_free_q_vectors(adapter);
i40evf_free_queues(adapter);
err = i40evf_init_interrupt_scheme(adapter);
if (err)
goto err;
netif_tx_stop_all_queues(netdev);
err = i40evf_request_misc_irq(adapter);
if (err)
goto err;
set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
i40evf_map_rings_to_vectors(adapter);
if (RSS_AQ(adapter))
adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_RSS;
else
err = i40evf_init_rss(adapter);
err:
return err;
}
/** /**
* i40evf_watchdog_timer - Periodic call-back timer * i40evf_watchdog_timer - Periodic call-back timer
* @data: pointer to adapter disguised as unsigned long * @data: pointer to adapter disguised as unsigned long
...@@ -1885,8 +1931,15 @@ static void i40evf_reset_task(struct work_struct *work) ...@@ -1885,8 +1931,15 @@ static void i40evf_reset_task(struct work_struct *work)
if (err) if (err)
dev_info(&adapter->pdev->dev, "Failed to init adminq: %d\n", dev_info(&adapter->pdev->dev, "Failed to init adminq: %d\n",
err); err);
adapter->aq_required = 0;
adapter->aq_required = I40EVF_FLAG_AQ_GET_CONFIG; if (adapter->flags & I40EVF_FLAG_REINIT_ITR_NEEDED) {
err = i40evf_reinit_interrupt_scheme(adapter);
if (err)
goto reset_err;
}
adapter->aq_required |= I40EVF_FLAG_AQ_GET_CONFIG;
adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS; adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
/* re-add all MAC filters */ /* re-add all MAC filters */
...@@ -1916,6 +1969,15 @@ static void i40evf_reset_task(struct work_struct *work) ...@@ -1916,6 +1969,15 @@ static void i40evf_reset_task(struct work_struct *work)
if (err) if (err)
goto reset_err; goto reset_err;
if (adapter->flags & I40EVF_FLAG_REINIT_ITR_NEEDED) {
err = i40evf_request_traffic_irqs(adapter,
netdev->name);
if (err)
goto reset_err;
adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
}
i40evf_configure(adapter); i40evf_configure(adapter);
i40evf_up_complete(adapter); i40evf_up_complete(adapter);
...@@ -2431,9 +2493,9 @@ static int i40evf_check_reset_complete(struct i40e_hw *hw) ...@@ -2431,9 +2493,9 @@ static int i40evf_check_reset_complete(struct i40e_hw *hw)
int i40evf_process_config(struct i40evf_adapter *adapter) int i40evf_process_config(struct i40evf_adapter *adapter)
{ {
struct virtchnl_vf_resource *vfres = adapter->vf_res; struct virtchnl_vf_resource *vfres = adapter->vf_res;
int i, num_req_queues = adapter->num_req_queues;
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
struct i40e_vsi *vsi = &adapter->vsi; struct i40e_vsi *vsi = &adapter->vsi;
int i;
netdev_features_t hw_enc_features; netdev_features_t hw_enc_features;
netdev_features_t hw_features; netdev_features_t hw_features;
...@@ -2447,6 +2509,23 @@ int i40evf_process_config(struct i40evf_adapter *adapter) ...@@ -2447,6 +2509,23 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
return -ENODEV; return -ENODEV;
} }
if (num_req_queues &&
num_req_queues != adapter->vsi_res->num_queue_pairs) {
/* Problem. The PF gave us fewer queues than what we had
* negotiated in our request. Need a reset to see if we can't
* get back to a working state.
*/
dev_err(&adapter->pdev->dev,
"Requested %d queues, but PF only gave us %d.\n",
num_req_queues,
adapter->vsi_res->num_queue_pairs);
adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
adapter->num_req_queues = adapter->vsi_res->num_queue_pairs;
i40evf_schedule_reset(adapter);
return -ENODEV;
}
adapter->num_req_queues = 0;
hw_enc_features = NETIF_F_SG | hw_enc_features = NETIF_F_SG |
NETIF_F_IP_CSUM | NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM | NETIF_F_IPV6_CSUM |
......
...@@ -160,7 +160,8 @@ int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter) ...@@ -160,7 +160,8 @@ int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter)
VIRTCHNL_VF_OFFLOAD_WB_ON_ITR | VIRTCHNL_VF_OFFLOAD_WB_ON_ITR |
VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 | VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 |
VIRTCHNL_VF_OFFLOAD_ENCAP | VIRTCHNL_VF_OFFLOAD_ENCAP |
VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM; VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM |
VIRTCHNL_VF_OFFLOAD_REQ_QUEUES;
adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES; adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES;
adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_CONFIG; adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_CONFIG;
...@@ -384,6 +385,32 @@ void i40evf_map_queues(struct i40evf_adapter *adapter) ...@@ -384,6 +385,32 @@ void i40evf_map_queues(struct i40evf_adapter *adapter)
kfree(vimi); kfree(vimi);
} }
/**
* i40evf_request_queues
* @adapter: adapter structure
* @num: number of requested queues
*
* We get a default number of queues from the PF. This enables us to request a
* different number. Returns 0 on success, negative on failure
**/
int i40evf_request_queues(struct i40evf_adapter *adapter, int num)
{
struct virtchnl_vf_res_request vfres;
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
dev_err(&adapter->pdev->dev, "Cannot request queues, command %d pending\n",
adapter->current_op);
return -EBUSY;
}
vfres.num_queue_pairs = num;
adapter->current_op = VIRTCHNL_OP_REQUEST_QUEUES;
return i40evf_send_pf_msg(adapter, VIRTCHNL_OP_REQUEST_QUEUES,
(u8 *)&vfres, sizeof(vfres));
}
/** /**
* i40evf_add_ether_addrs * i40evf_add_ether_addrs
* @adapter: adapter structure * @adapter: adapter structure
...@@ -1068,6 +1095,21 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, ...@@ -1068,6 +1095,21 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
"Invalid message %d from PF\n", v_opcode); "Invalid message %d from PF\n", v_opcode);
} }
break; break;
case VIRTCHNL_OP_REQUEST_QUEUES: {
struct virtchnl_vf_res_request *vfres =
(struct virtchnl_vf_res_request *)msg;
if (vfres->num_queue_pairs == adapter->num_req_queues) {
adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
i40evf_schedule_reset(adapter);
} else {
dev_info(&adapter->pdev->dev,
"Requested %d queues, PF can support %d\n",
adapter->num_req_queues,
vfres->num_queue_pairs);
adapter->num_req_queues = 0;
}
}
break;
default: default:
if (adapter->current_op && (v_opcode != adapter->current_op)) if (adapter->current_op && (v_opcode != adapter->current_op))
dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n", dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment