Commit db7e9f7c 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 2016-12-02

This series contains updates to i40e and i40evf only.

Alex provides changes so that we are much more robust about defining what
we can and cannot offload in i40e and i40evf by doing additional checks
other than L4 tunnel header length.

Jake provides several fixes/changes, first cleaning up a label that is
unnecessary, as well as cleaned up the use of a "magic number".  Clarified
the code by separating the global private flags and the regular private
flags per interface into two arrays, so that future additions will not
produce duplication and buggy code.  Adds additional checks to protect
against NULL values for msix_entries and q_vectors pointers.

Michal adds Clause22 method for accessing registers for some external
PHYs.

Piotr adds additional protocol support for the admin queue discover
capabilities function.

Tushar Dave fixes a panic seen on SPARC, where writel() should not be
used to write directly to a memory address but only to a memory mapped
I/O address otherwise it causes data access exceptions.

Joe Perches separates out a section of code into its own function, to
help reduce i40evf_reset_task() a bit.

Alan fixes an issue by checking for NULL before dereferencing msix_entries
and returning early in the case where it is NULL within the i40evf_close()
code path.

Henry provides code cleanup to remove unreachable and redundant sections
of code.  Fixed up an issue where new NICs were not identifying "unknown
PHYs" correctly.

Harshitha fixes a issue where the ethtool "Supported Link" modes list
backplane interfaces on X722 devices for 10 GbE with SFP+ and Cortina
retimer, where these interfaces should not be visible to the user since
they cannot use them.

Carolyn changes an X722 informational message so that it only appears
when extra messages are desired.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2bb14878 23bb6dc3
...@@ -359,6 +359,7 @@ struct i40e_pf { ...@@ -359,6 +359,7 @@ struct i40e_pf {
#define I40E_FLAG_HAVE_10GBASET_PHY BIT_ULL(48) #define I40E_FLAG_HAVE_10GBASET_PHY BIT_ULL(48)
#define I40E_FLAG_PF_MAC BIT_ULL(50) #define I40E_FLAG_PF_MAC BIT_ULL(50)
#define I40E_FLAG_TRUE_PROMISC_SUPPORT BIT_ULL(51) #define I40E_FLAG_TRUE_PROMISC_SUPPORT BIT_ULL(51)
#define I40E_FLAG_HAVE_CRT_RETIMER BIT_ULL(52)
/* tracks features that get auto disabled by errors */ /* tracks features that get auto disabled by errors */
u64 auto_disable_flags; u64 auto_disable_flags;
......
...@@ -1854,7 +1854,8 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw, ...@@ -1854,7 +1854,8 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
else else
hw_link_info->lse_enable = false; hw_link_info->lse_enable = false;
if ((hw->aq.fw_maj_ver < 4 || (hw->aq.fw_maj_ver == 4 && if ((hw->mac.type == I40E_MAC_XL710) &&
(hw->aq.fw_maj_ver < 4 || (hw->aq.fw_maj_ver == 4 &&
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;
...@@ -2168,6 +2169,40 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw, ...@@ -2168,6 +2169,40 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,
return status; return status;
} }
/**
* i40e_aq_set_vsi_bc_promisc_on_vlan
* @hw: pointer to the hw struct
* @seid: vsi number
* @enable: set broadcast promiscuous enable/disable for a given VLAN
* @vid: The VLAN tag filter - capture any broadcast packet with this VLAN tag
* @cmd_details: pointer to command details structure or NULL
**/
i40e_status i40e_aq_set_vsi_bc_promisc_on_vlan(struct i40e_hw *hw,
u16 seid, bool enable, u16 vid,
struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_desc desc;
struct i40e_aqc_set_vsi_promiscuous_modes *cmd =
(struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw;
i40e_status status;
u16 flags = 0;
i40e_fill_default_direct_cmd_desc(&desc,
i40e_aqc_opc_set_vsi_promiscuous_modes);
if (enable)
flags |= I40E_AQC_SET_VSI_PROMISC_BROADCAST;
cmd->promiscuous_flags = cpu_to_le16(flags);
cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_BROADCAST);
cmd->seid = cpu_to_le16(seid);
cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID);
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
return status;
}
/** /**
* i40e_aq_set_vsi_broadcast * i40e_aq_set_vsi_broadcast
* @hw: pointer to the hw struct * @hw: pointer to the hw struct
...@@ -3147,6 +3182,14 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff, ...@@ -3147,6 +3182,14 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
break; break;
case I40E_AQ_CAP_ID_MNG_MODE: case I40E_AQ_CAP_ID_MNG_MODE:
p->management_mode = number; p->management_mode = number;
if (major_rev > 1) {
p->mng_protocols_over_mctp = logical_id;
i40e_debug(hw, I40E_DEBUG_INIT,
"HW Capability: Protocols over MCTP = %d\n",
p->mng_protocols_over_mctp);
} else {
p->mng_protocols_over_mctp = 0;
}
break; break;
case I40E_AQ_CAP_ID_NPAR_ACTIVE: case I40E_AQ_CAP_ID_NPAR_ACTIVE:
p->npar_enable = number; p->npar_enable = number;
...@@ -4396,7 +4439,92 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw, ...@@ -4396,7 +4439,92 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw,
} }
/** /**
* i40e_read_phy_register * i40e_read_phy_register_clause22
* @hw: pointer to the HW structure
* @reg: register address in the page
* @phy_adr: PHY address on MDIO interface
* @value: PHY register value
*
* Reads specified PHY register value
**/
i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw,
u16 reg, u8 phy_addr, u16 *value)
{
i40e_status status = I40E_ERR_TIMEOUT;
u8 port_num = (u8)hw->func_caps.mdio_port_num;
u32 command = 0;
u16 retry = 1000;
command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_CLAUSE22_OPCODE_READ_MASK) |
(I40E_MDIO_CLAUSE22_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command);
do {
command = rd32(hw, I40E_GLGEN_MSCA(port_num));
if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
status = 0;
break;
}
udelay(10);
retry--;
} while (retry);
if (status) {
i40e_debug(hw, I40E_DEBUG_PHY,
"PHY: Can't write command to external PHY.\n");
} else {
command = rd32(hw, I40E_GLGEN_MSRWD(port_num));
*value = (command & I40E_GLGEN_MSRWD_MDIRDDATA_MASK) >>
I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT;
}
return status;
}
/**
* i40e_write_phy_register_clause22
* @hw: pointer to the HW structure
* @reg: register address in the page
* @phy_adr: PHY address on MDIO interface
* @value: PHY register value
*
* Writes specified PHY register value
**/
i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
u16 reg, u8 phy_addr, u16 value)
{
i40e_status status = I40E_ERR_TIMEOUT;
u8 port_num = (u8)hw->func_caps.mdio_port_num;
u32 command = 0;
u16 retry = 1000;
command = value << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT;
wr32(hw, I40E_GLGEN_MSRWD(port_num), command);
command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK) |
(I40E_MDIO_CLAUSE22_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command);
do {
command = rd32(hw, I40E_GLGEN_MSCA(port_num));
if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
status = 0;
break;
}
udelay(10);
retry--;
} while (retry);
return status;
}
/**
* i40e_read_phy_register_clause45
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
* @page: registers page number * @page: registers page number
* @reg: register address in the page * @reg: register address in the page
...@@ -4405,9 +4533,8 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw, ...@@ -4405,9 +4533,8 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw,
* *
* Reads specified PHY register value * Reads specified PHY register value
**/ **/
i40e_status i40e_read_phy_register(struct i40e_hw *hw, i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u8 page, u16 reg, u8 phy_addr, u16 *value)
u16 *value)
{ {
i40e_status status = I40E_ERR_TIMEOUT; i40e_status status = I40E_ERR_TIMEOUT;
u32 command = 0; u32 command = 0;
...@@ -4417,8 +4544,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw, ...@@ -4417,8 +4544,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,
command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) | command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
(page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_ADDRESS) | (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
(I40E_MDIO_STCODE) | (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) | (I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK); (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command); wr32(hw, I40E_GLGEN_MSCA(port_num), command);
...@@ -4440,8 +4567,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw, ...@@ -4440,8 +4567,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,
command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_READ) | (I40E_MDIO_CLAUSE45_OPCODE_READ_MASK) |
(I40E_MDIO_STCODE) | (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) | (I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK); (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
status = I40E_ERR_TIMEOUT; status = I40E_ERR_TIMEOUT;
...@@ -4471,7 +4598,7 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw, ...@@ -4471,7 +4598,7 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,
} }
/** /**
* i40e_write_phy_register * i40e_write_phy_register_clause45
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
* @page: registers page number * @page: registers page number
* @reg: register address in the page * @reg: register address in the page
...@@ -4480,9 +4607,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw, ...@@ -4480,9 +4607,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,
* *
* Writes value to specified PHY register * Writes value to specified PHY register
**/ **/
i40e_status i40e_write_phy_register(struct i40e_hw *hw, i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u8 page, u16 reg, u8 phy_addr, u16 value)
u16 value)
{ {
i40e_status status = I40E_ERR_TIMEOUT; i40e_status status = I40E_ERR_TIMEOUT;
u32 command = 0; u32 command = 0;
...@@ -4492,8 +4618,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw, ...@@ -4492,8 +4618,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw,
command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) | command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
(page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_ADDRESS) | (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
(I40E_MDIO_STCODE) | (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) | (I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK); (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command); wr32(hw, I40E_GLGEN_MSCA(port_num), command);
...@@ -4517,8 +4643,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw, ...@@ -4517,8 +4643,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw,
command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_WRITE) | (I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK) |
(I40E_MDIO_STCODE) | (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) | (I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK); (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
status = I40E_ERR_TIMEOUT; status = I40E_ERR_TIMEOUT;
...@@ -4580,14 +4706,16 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw, ...@@ -4580,14 +4706,16 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++, for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
led_addr++) { led_addr++) {
status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, status = i40e_read_phy_register_clause45(hw,
led_addr, phy_addr, &led_reg); I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr,
&led_reg);
if (status) if (status)
goto phy_blinking_end; goto phy_blinking_end;
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(hw, status = i40e_write_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_addr, phy_addr,
led_reg); led_reg);
...@@ -4599,20 +4727,18 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw, ...@@ -4599,20 +4727,18 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
if (time > 0 && interval > 0) { if (time > 0 && interval > 0) {
for (i = 0; i < time * 1000; i += interval) { for (i = 0; i < time * 1000; i += interval) {
status = i40e_read_phy_register(hw, status = i40e_read_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_addr, phy_addr, &led_reg);
&led_reg);
if (status) if (status)
goto restore_config; goto restore_config;
if (led_reg & I40E_PHY_LED_MANUAL_ON) if (led_reg & I40E_PHY_LED_MANUAL_ON)
led_reg = 0; led_reg = 0;
else else
led_reg = I40E_PHY_LED_MANUAL_ON; led_reg = I40E_PHY_LED_MANUAL_ON;
status = i40e_write_phy_register(hw, status = i40e_write_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_addr, phy_addr, led_reg);
led_reg);
if (status) if (status)
goto restore_config; goto restore_config;
msleep(interval); msleep(interval);
...@@ -4620,8 +4746,9 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw, ...@@ -4620,8 +4746,9 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
} }
restore_config: restore_config:
status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, status = i40e_write_phy_register_clause45(hw,
phy_addr, led_ctl); I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_ctl);
phy_blinking_end: phy_blinking_end:
return status; return status;
...@@ -4652,8 +4779,10 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr, ...@@ -4652,8 +4779,10 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++, for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
temp_addr++) { temp_addr++) {
status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, status = i40e_read_phy_register_clause45(hw,
temp_addr, phy_addr, &reg_val); I40E_PHY_COM_REG_PAGE,
temp_addr, phy_addr,
&reg_val);
if (status) if (status)
return status; return status;
*val = reg_val; *val = reg_val;
...@@ -4686,20 +4815,21 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on, ...@@ -4686,20 +4815,21 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on,
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);
phy_addr = i40e_get_phy_address(hw, port_num); phy_addr = i40e_get_phy_address(hw, port_num);
status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, led_addr, phy_addr, &led_reg);
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(hw, I40E_PHY_COM_REG_PAGE, status = i40e_write_phy_register_clause45(hw,
led_addr, phy_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(hw, I40E_PHY_COM_REG_PAGE, status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, &led_reg); led_addr, phy_addr, &led_reg);
if (status) if (status)
goto restore_config; goto restore_config;
...@@ -4707,20 +4837,20 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on, ...@@ -4707,20 +4837,20 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool 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(hw, I40E_PHY_COM_REG_PAGE, status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_reg); led_addr, phy_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(hw, status = i40e_write_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_ctl); led_addr, phy_addr, led_ctl);
} }
return status; return status;
restore_config: restore_config:
status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
phy_addr, led_ctl); led_addr, phy_addr, led_ctl);
return status; return status;
} }
......
...@@ -228,26 +228,22 @@ static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = { ...@@ -228,26 +228,22 @@ static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = {
#define I40E_TEST_LEN (sizeof(i40e_gstrings_test) / ETH_GSTRING_LEN) #define I40E_TEST_LEN (sizeof(i40e_gstrings_test) / ETH_GSTRING_LEN)
static const char i40e_priv_flags_strings_gl[][ETH_GSTRING_LEN] = { static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = {
"MFP", "MFP",
"LinkPolling", "LinkPolling",
"flow-director-atr", "flow-director-atr",
"veb-stats", "veb-stats",
"hw-atr-eviction", "hw-atr-eviction",
"vf-true-promisc-support",
}; };
#define I40E_PRIV_FLAGS_GL_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings_gl) #define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings)
static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = { /* Private flags with a global effect, restricted to PF 0 */
"NPAR", static const char i40e_gl_priv_flags_strings[][ETH_GSTRING_LEN] = {
"LinkPolling", "vf-true-promisc-support",
"flow-director-atr",
"veb-stats",
"hw-atr-eviction",
}; };
#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings) #define I40E_GL_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gl_priv_flags_strings)
/** /**
* i40e_partition_setting_complaint - generic complaint for MFP restriction * i40e_partition_setting_complaint - generic complaint for MFP restriction
...@@ -349,10 +345,12 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported, ...@@ -349,10 +345,12 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
*advertising |= ADVERTISED_20000baseKR2_Full; *advertising |= ADVERTISED_20000baseKR2_Full;
} }
if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR) { if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR) {
if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
*supported |= SUPPORTED_10000baseKR_Full | *supported |= SUPPORTED_10000baseKR_Full |
SUPPORTED_Autoneg; SUPPORTED_Autoneg;
*advertising |= ADVERTISED_Autoneg; *advertising |= ADVERTISED_Autoneg;
if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
*advertising |= ADVERTISED_10000baseKR_Full; *advertising |= ADVERTISED_10000baseKR_Full;
} }
if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4) { if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4) {
...@@ -363,10 +361,12 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported, ...@@ -363,10 +361,12 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
*advertising |= ADVERTISED_10000baseKX4_Full; *advertising |= ADVERTISED_10000baseKX4_Full;
} }
if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX) { if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX) {
if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
*supported |= SUPPORTED_1000baseKX_Full | *supported |= SUPPORTED_1000baseKX_Full |
SUPPORTED_Autoneg; SUPPORTED_Autoneg;
*advertising |= ADVERTISED_Autoneg; *advertising |= ADVERTISED_Autoneg;
if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
*advertising |= ADVERTISED_1000baseKX_Full; *advertising |= ADVERTISED_1000baseKX_Full;
} }
} }
...@@ -1194,10 +1194,9 @@ static void i40e_get_drvinfo(struct net_device *netdev, ...@@ -1194,10 +1194,9 @@ static void i40e_get_drvinfo(struct net_device *netdev,
sizeof(drvinfo->fw_version)); sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, pci_name(pf->pdev), strlcpy(drvinfo->bus_info, pci_name(pf->pdev),
sizeof(drvinfo->bus_info)); sizeof(drvinfo->bus_info));
if (pf->hw.pf_id == 0)
drvinfo->n_priv_flags = I40E_PRIV_FLAGS_GL_STR_LEN;
else
drvinfo->n_priv_flags = I40E_PRIV_FLAGS_STR_LEN; drvinfo->n_priv_flags = I40E_PRIV_FLAGS_STR_LEN;
if (pf->hw.pf_id == 0)
drvinfo->n_priv_flags += I40E_GL_PRIV_FLAGS_STR_LEN;
} }
static void i40e_get_ringparam(struct net_device *netdev, static void i40e_get_ringparam(struct net_device *netdev,
...@@ -1222,6 +1221,7 @@ static int i40e_set_ringparam(struct net_device *netdev, ...@@ -1222,6 +1221,7 @@ static int i40e_set_ringparam(struct net_device *netdev,
{ {
struct i40e_ring *tx_rings = NULL, *rx_rings = NULL; struct i40e_ring *tx_rings = NULL, *rx_rings = NULL;
struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_hw *hw = &np->vsi->back->hw;
struct i40e_vsi *vsi = np->vsi; struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back; struct i40e_pf *pf = vsi->back;
u32 new_rx_count, new_tx_count; u32 new_rx_count, new_tx_count;
...@@ -1314,10 +1314,6 @@ static int i40e_set_ringparam(struct net_device *netdev, ...@@ -1314,10 +1314,6 @@ static int i40e_set_ringparam(struct net_device *netdev,
} }
for (i = 0; i < vsi->num_queue_pairs; i++) { for (i = 0; i < vsi->num_queue_pairs; i++) {
/* this is to allow wr32 to have something to write to
* during early allocation of Rx buffers
*/
u32 __iomem faketail = 0;
struct i40e_ring *ring; struct i40e_ring *ring;
u16 unused; u16 unused;
...@@ -1329,7 +1325,10 @@ static int i40e_set_ringparam(struct net_device *netdev, ...@@ -1329,7 +1325,10 @@ static int i40e_set_ringparam(struct net_device *netdev,
*/ */
rx_rings[i].desc = NULL; rx_rings[i].desc = NULL;
rx_rings[i].rx_bi = NULL; rx_rings[i].rx_bi = NULL;
rx_rings[i].tail = (u8 __iomem *)&faketail; /* this is to allow wr32 to have something to write to
* during early allocation of Rx buffers
*/
rx_rings[i].tail = hw->hw_addr + I40E_PRTGEN_STATUS;
err = i40e_setup_rx_descriptors(&rx_rings[i]); err = i40e_setup_rx_descriptors(&rx_rings[i]);
if (err) if (err)
goto rx_unwind; goto rx_unwind;
...@@ -1425,10 +1424,8 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset) ...@@ -1425,10 +1424,8 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset)
return I40E_VSI_STATS_LEN(netdev); return I40E_VSI_STATS_LEN(netdev);
} }
case ETH_SS_PRIV_FLAGS: case ETH_SS_PRIV_FLAGS:
if (pf->hw.pf_id == 0) return I40E_PRIV_FLAGS_STR_LEN +
return I40E_PRIV_FLAGS_GL_STR_LEN; (pf->hw.pf_id == 0 ? I40E_GL_PRIV_FLAGS_STR_LEN : 0);
else
return I40E_PRIV_FLAGS_STR_LEN;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -1539,10 +1536,8 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset, ...@@ -1539,10 +1536,8 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
switch (stringset) { switch (stringset) {
case ETH_SS_TEST: case ETH_SS_TEST:
for (i = 0; i < I40E_TEST_LEN; i++) { memcpy(data, i40e_gstrings_test,
memcpy(data, i40e_gstrings_test[i], ETH_GSTRING_LEN); I40E_TEST_LEN * ETH_GSTRING_LEN);
data += ETH_GSTRING_LEN;
}
break; break;
case ETH_SS_STATS: case ETH_SS_STATS:
for (i = 0; i < I40E_NETDEV_STATS_LEN; i++) { for (i = 0; i < I40E_NETDEV_STATS_LEN; i++) {
...@@ -1626,19 +1621,12 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset, ...@@ -1626,19 +1621,12 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
/* BUG_ON(p - data != I40E_STATS_LEN * ETH_GSTRING_LEN); */ /* BUG_ON(p - data != I40E_STATS_LEN * ETH_GSTRING_LEN); */
break; break;
case ETH_SS_PRIV_FLAGS: case ETH_SS_PRIV_FLAGS:
if (pf->hw.pf_id == 0) { memcpy(data, i40e_priv_flags_strings,
for (i = 0; i < I40E_PRIV_FLAGS_GL_STR_LEN; i++) { I40E_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);
memcpy(data, i40e_priv_flags_strings_gl[i], data += I40E_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN;
ETH_GSTRING_LEN); if (pf->hw.pf_id == 0)
data += ETH_GSTRING_LEN; memcpy(data, i40e_gl_priv_flags_strings,
} I40E_GL_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);
} else {
for (i = 0; i < I40E_PRIV_FLAGS_STR_LEN; i++) {
memcpy(data, i40e_priv_flags_strings[i],
ETH_GSTRING_LEN);
data += ETH_GSTRING_LEN;
}
}
break; break;
default: default:
break; break;
......
...@@ -1211,12 +1211,12 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi) ...@@ -1211,12 +1211,12 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi)
* i40e_add_filter. * i40e_add_filter.
* *
* 2) the only place where filters are actually removed is in * 2) the only place where filters are actually removed is in
* i40e_vsi_sync_filters_subtask. * i40e_sync_filters_subtask.
* *
* Thus, we can simply use a boolean value, has_vlan_filters which we * Thus, we can simply use a boolean value, has_vlan_filters which we
* will set to true when we add a VLAN filter in i40e_add_filter. Then * will set to true when we add a VLAN filter in i40e_add_filter. Then
* we have to perform the full search after deleting filters in * we have to perform the full search after deleting filters in
* i40e_vsi_sync_filters_subtask, but we already have to search * i40e_sync_filters_subtask, but we already have to search
* filters here and can perform the check at the same time. This * filters here and can perform the check at the same time. This
* results in avoiding embedding a loop for VLAN mode inside another * results in avoiding embedding a loop for VLAN mode inside another
* loop over all the filters, and should maintain correctness as noted * loop over all the filters, and should maintain correctness as noted
...@@ -1245,13 +1245,6 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, ...@@ -1245,13 +1245,6 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
if (!vsi || !macaddr) if (!vsi || !macaddr)
return NULL; return NULL;
/* Do not allow broadcast filter to be added since broadcast filter
* is added as part of add VSI for any newly created VSI except
* FDIR VSI
*/
if (is_broadcast_ether_addr(macaddr))
return NULL;
f = i40e_find_filter(vsi, macaddr, vlan); f = i40e_find_filter(vsi, macaddr, vlan);
if (!f) { if (!f) {
f = kzalloc(sizeof(*f), GFP_ATOMIC); f = kzalloc(sizeof(*f), GFP_ATOMIC);
...@@ -1856,6 +1849,47 @@ void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name, ...@@ -1856,6 +1849,47 @@ void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name,
} }
} }
/**
* i40e_aqc_broadcast_filter - Set promiscuous broadcast flags
* @vsi: pointer to the VSI
* @f: filter data
*
* This function sets or clears the promiscuous broadcast flags for VLAN
* filters in order to properly receive broadcast frames. Assumes that only
* broadcast filters are passed.
**/
static
void i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,
struct i40e_mac_filter *f)
{
bool enable = f->state == I40E_FILTER_NEW;
struct i40e_hw *hw = &vsi->back->hw;
i40e_status aq_ret;
if (f->vlan == I40E_VLAN_ANY) {
aq_ret = i40e_aq_set_vsi_broadcast(hw,
vsi->seid,
enable,
NULL);
} else {
aq_ret = i40e_aq_set_vsi_bc_promisc_on_vlan(hw,
vsi->seid,
enable,
f->vlan,
NULL);
}
if (aq_ret) {
dev_warn(&vsi->back->pdev->dev,
"Error %s setting broadcast promiscuous mode on %s\n",
i40e_aq_str(hw, hw->aq.asq_last_status),
vsi_name);
f->state = I40E_FILTER_FAILED;
} else if (enable) {
f->state = I40E_FILTER_ACTIVE;
}
}
/** /**
* i40e_sync_vsi_filters - Update the VSI filter list to the HW * i40e_sync_vsi_filters - Update the VSI filter list to the HW
* @vsi: ptr to the VSI * @vsi: ptr to the VSI
...@@ -2004,6 +2038,17 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) ...@@ -2004,6 +2038,17 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
hlist_for_each_entry_safe(f, h, &tmp_del_list, hlist) { hlist_for_each_entry_safe(f, h, &tmp_del_list, hlist) {
cmd_flags = 0; cmd_flags = 0;
/* handle broadcast filters by updating the broadcast
* promiscuous flag instead of deleting a MAC filter.
*/
if (is_broadcast_ether_addr(f->macaddr)) {
i40e_aqc_broadcast_filter(vsi, vsi_name, f);
hlist_del(&f->hlist);
kfree(f);
continue;
}
/* add to delete list */ /* add to delete list */
ether_addr_copy(del_list[num_del].mac_addr, f->macaddr); ether_addr_copy(del_list[num_del].mac_addr, f->macaddr);
if (f->vlan == I40E_VLAN_ANY) { if (f->vlan == I40E_VLAN_ANY) {
...@@ -2060,12 +2105,25 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) ...@@ -2060,12 +2105,25 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
goto err_no_memory; goto err_no_memory;
num_add = 0; num_add = 0;
hlist_for_each_entry(f, &tmp_add_list, hlist) { hlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) {
if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
&vsi->state)) { &vsi->state)) {
f->state = I40E_FILTER_FAILED; f->state = I40E_FILTER_FAILED;
continue; continue;
} }
/* handle broadcast filters by updating the broadcast
* promiscuous flag instead of adding a MAC filter.
*/
if (is_broadcast_ether_addr(f->macaddr)) {
u64 key = i40e_addr_to_hkey(f->macaddr);
i40e_aqc_broadcast_filter(vsi, vsi_name, f);
hlist_del(&f->hlist);
hash_add(vsi->mac_filter_hash, &f->hlist, key);
continue;
}
/* add to add array */ /* add to add array */
if (num_add == 0) if (num_add == 0)
add_head = f; add_head = f;
...@@ -2549,7 +2607,7 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev, ...@@ -2549,7 +2607,7 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev,
struct i40e_vsi *vsi = np->vsi; struct i40e_vsi *vsi = np->vsi;
int ret = 0; int ret = 0;
if (vid > 4095) if (vid >= VLAN_N_VID)
return -EINVAL; return -EINVAL;
/* If the network stack called us with vid = 0 then /* If the network stack called us with vid = 0 then
...@@ -2561,7 +2619,7 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev, ...@@ -2561,7 +2619,7 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev,
if (vid) if (vid)
ret = i40e_vsi_add_vlan(vsi, vid); ret = i40e_vsi_add_vlan(vsi, vid);
if (!ret && (vid < VLAN_N_VID)) if (!ret)
set_bit(vid, vsi->active_vlans); set_bit(vid, vsi->active_vlans);
return ret; return ret;
...@@ -3521,7 +3579,7 @@ static irqreturn_t i40e_intr(int irq, void *data) ...@@ -3521,7 +3579,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
(ena_mask & I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK)) { (ena_mask & I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK)) {
ena_mask &= ~I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK; ena_mask &= ~I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK;
icr0 &= ~I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK; icr0 &= ~I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK;
dev_info(&pf->pdev->dev, "cleared PE_CRITERR\n"); dev_dbg(&pf->pdev->dev, "cleared PE_CRITERR\n");
} }
/* only q0 is used in MSI/Legacy mode, and none are used in MSIX */ /* only q0 is used in MSI/Legacy mode, and none are used in MSIX */
...@@ -9070,10 +9128,6 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, ...@@ -9070,10 +9128,6 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
0, 0, nlflags, filter_mask, NULL); 0, 0, nlflags, filter_mask, NULL);
} }
/* Hardware supports L4 tunnel length of 128B (=2^7) which includes
* inner mac plus all inner ethertypes.
*/
#define I40E_MAX_TUNNEL_HDR_LEN 128
/** /**
* i40e_features_check - Validate encapsulated packet conforms to limits * i40e_features_check - Validate encapsulated packet conforms to limits
* @skb: skb buff * @skb: skb buff
...@@ -9084,12 +9138,52 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb, ...@@ -9084,12 +9138,52 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
netdev_features_t features) netdev_features_t features)
{ {
if (skb->encapsulation && size_t len;
((skb_inner_network_header(skb) - skb_transport_header(skb)) >
I40E_MAX_TUNNEL_HDR_LEN))
return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
/* No point in doing any of this if neither checksum nor GSO are
* being requested for this frame. We can rule out both by just
* checking for CHECKSUM_PARTIAL
*/
if (skb->ip_summed != CHECKSUM_PARTIAL)
return features; return features;
/* We cannot support GSO if the MSS is going to be less than
* 64 bytes. If it is then we need to drop support for GSO.
*/
if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
features &= ~NETIF_F_GSO_MASK;
/* MACLEN can support at most 63 words */
len = skb_network_header(skb) - skb->data;
if (len & ~(63 * 2))
goto out_err;
/* IPLEN and EIPLEN can support at most 127 dwords */
len = skb_transport_header(skb) - skb_network_header(skb);
if (len & ~(127 * 4))
goto out_err;
if (skb->encapsulation) {
/* L4TUNLEN can support 127 words */
len = skb_inner_network_header(skb) - skb_transport_header(skb);
if (len & ~(127 * 2))
goto out_err;
/* IPLEN can support at most 127 dwords */
len = skb_inner_transport_header(skb) -
skb_inner_network_header(skb);
if (len & ~(127 * 4))
goto out_err;
}
/* No need to validate L4LEN as TCP is the only protocol with a
* a flexible value and we support all possible values supported
* by TCP, which is at most 15 dwords
*/
return features;
out_err:
return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
} }
static const struct net_device_ops i40e_netdev_ops = { static const struct net_device_ops i40e_netdev_ops = {
...@@ -9142,6 +9236,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) ...@@ -9142,6 +9236,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
struct i40e_netdev_priv *np; struct i40e_netdev_priv *np;
struct net_device *netdev; struct net_device *netdev;
u8 broadcast[ETH_ALEN];
u8 mac_addr[ETH_ALEN]; u8 mac_addr[ETH_ALEN];
int etherdev_size; int etherdev_size;
...@@ -9210,6 +9305,24 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) ...@@ -9210,6 +9305,24 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
spin_unlock_bh(&vsi->mac_filter_hash_lock); spin_unlock_bh(&vsi->mac_filter_hash_lock);
} }
/* Add the broadcast filter so that we initially will receive
* broadcast packets. Note that when a new VLAN is first added the
* driver will convert all filters marked I40E_VLAN_ANY into VLAN
* specific filters as part of transitioning into "vlan" operation.
* When more VLANs are added, the driver will copy each existing MAC
* filter and add it for the new VLAN.
*
* Broadcast filters are handled specially by
* i40e_sync_filters_subtask, as the driver must to set the broadcast
* promiscuous bit instead of adding this directly as a MAC/VLAN
* filter. The subtask will update the correct broadcast promiscuous
* bits as VLANs become active or inactive.
*/
eth_broadcast_addr(broadcast);
spin_lock_bh(&vsi->mac_filter_hash_lock);
i40e_add_filter(vsi, broadcast, I40E_VLAN_ANY);
spin_unlock_bh(&vsi->mac_filter_hash_lock);
ether_addr_copy(netdev->dev_addr, mac_addr); ether_addr_copy(netdev->dev_addr, mac_addr);
ether_addr_copy(netdev->perm_addr, mac_addr); ether_addr_copy(netdev->perm_addr, mac_addr);
...@@ -9292,7 +9405,6 @@ int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi) ...@@ -9292,7 +9405,6 @@ int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi)
static int i40e_add_vsi(struct i40e_vsi *vsi) static int i40e_add_vsi(struct i40e_vsi *vsi)
{ {
int ret = -ENODEV; int ret = -ENODEV;
i40e_status aq_ret = 0;
struct i40e_pf *pf = vsi->back; struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
struct i40e_vsi_context ctxt; struct i40e_vsi_context ctxt;
...@@ -9482,18 +9594,6 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) ...@@ -9482,18 +9594,6 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
vsi->seid = ctxt.seid; vsi->seid = ctxt.seid;
vsi->id = ctxt.vsi_number; vsi->id = ctxt.vsi_number;
} }
/* Except FDIR VSI, for all othet VSI set the broadcast filter */
if (vsi->type != I40E_VSI_FDIR) {
aq_ret = i40e_aq_set_vsi_broadcast(hw, vsi->seid, true, NULL);
if (aq_ret) {
ret = i40e_aq_rc_to_posix(aq_ret,
hw->aq.asq_last_status);
dev_info(&pf->pdev->dev,
"set brdcast promisc failed, err %s, aq_err %s\n",
i40e_stat_str(hw, aq_ret),
i40e_aq_str(hw, hw->aq.asq_last_status));
}
}
vsi->active_filters = 0; vsi->active_filters = 0;
clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state); clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
...@@ -11266,7 +11366,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -11266,7 +11366,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if ((pf->hw.device_id == I40E_DEV_ID_10G_BASE_T) || if ((pf->hw.device_id == I40E_DEV_ID_10G_BASE_T) ||
(pf->hw.device_id == I40E_DEV_ID_10G_BASE_T4)) (pf->hw.device_id == I40E_DEV_ID_10G_BASE_T4))
pf->flags |= I40E_FLAG_HAVE_10GBASET_PHY; pf->flags |= I40E_FLAG_HAVE_10GBASET_PHY;
if (pf->hw.device_id == I40E_DEV_ID_SFP_I_X722)
pf->flags |= I40E_FLAG_HAVE_CRT_RETIMER;
/* print a string summarizing features */ /* print a string summarizing features */
i40e_print_features(pf); i40e_print_features(pf);
......
...@@ -144,6 +144,9 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw, ...@@ -144,6 +144,9 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,
u16 seid, bool enable, u16 seid, bool enable,
u16 vid, u16 vid,
struct i40e_asq_cmd_details *cmd_details); struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_set_vsi_bc_promisc_on_vlan(struct i40e_hw *hw,
u16 seid, bool enable, u16 vid,
struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw, i40e_status i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw,
u16 seid, bool enable, u16 seid, bool enable,
struct i40e_asq_cmd_details *cmd_details); struct i40e_asq_cmd_details *cmd_details);
...@@ -362,10 +365,14 @@ i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw, ...@@ -362,10 +365,14 @@ 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_read_phy_register(struct i40e_hw *hw, u8 page, 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(struct i40e_hw *hw, u8 page, i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
u16 reg, u8 phy_addr, u16 value); u16 reg, u8 phy_addr, u16 value);
i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u16 *value);
i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u16 value);
u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num); u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw, i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
u32 time, u32 interval); u32 time, u32 interval);
......
...@@ -90,13 +90,22 @@ enum i40e_debug_mask { ...@@ -90,13 +90,22 @@ enum i40e_debug_mask {
I40E_DEBUG_ALL = 0xFFFFFFFF I40E_DEBUG_ALL = 0xFFFFFFFF
}; };
#define I40E_MDIO_STCODE 0 #define I40E_MDIO_CLAUSE22_STCODE_MASK I40E_MASK(1, \
#define I40E_MDIO_OPCODE_ADDRESS 0 I40E_GLGEN_MSCA_STCODE_SHIFT)
#define I40E_MDIO_OPCODE_WRITE I40E_MASK(1, \ #define I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK I40E_MASK(1, \
I40E_GLGEN_MSCA_OPCODE_SHIFT) I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_OPCODE_READ_INC_ADDR I40E_MASK(2, \ #define I40E_MDIO_CLAUSE22_OPCODE_READ_MASK I40E_MASK(2, \
I40E_GLGEN_MSCA_OPCODE_SHIFT) I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_OPCODE_READ I40E_MASK(3, \
#define I40E_MDIO_CLAUSE45_STCODE_MASK I40E_MASK(0, \
I40E_GLGEN_MSCA_STCODE_SHIFT)
#define I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK I40E_MASK(0, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK I40E_MASK(1, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_CLAUSE45_OPCODE_READ_INC_ADDR_MASK I40E_MASK(2, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_CLAUSE45_OPCODE_READ_MASK I40E_MASK(3, \
I40E_GLGEN_MSCA_OPCODE_SHIFT) I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_PHY_COM_REG_PAGE 0x1E #define I40E_PHY_COM_REG_PAGE 0x1E
...@@ -254,6 +263,10 @@ struct i40e_hw_capabilities { ...@@ -254,6 +263,10 @@ struct i40e_hw_capabilities {
#define I40E_NVM_IMAGE_TYPE_UDP_CLOUD 0x3 #define I40E_NVM_IMAGE_TYPE_UDP_CLOUD 0x3
u32 management_mode; u32 management_mode;
u32 mng_protocols_over_mctp;
#define I40E_MNG_PROTOCOL_PLDM 0x2
#define I40E_MNG_PROTOCOL_OEM_COMMANDS 0x4
#define I40E_MNG_PROTOCOL_NCSI 0x8
u32 npar_enable; u32 npar_enable;
u32 os2bmc; u32 os2bmc;
u32 valid_functions; u32 valid_functions;
......
...@@ -674,6 +674,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) ...@@ -674,6 +674,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
} }
if (type == I40E_VSI_SRIOV) { if (type == I40E_VSI_SRIOV) {
u64 hena = i40e_pf_get_default_rss_hena(pf); u64 hena = i40e_pf_get_default_rss_hena(pf);
u8 broadcast[ETH_ALEN];
vf->lan_vsi_idx = vsi->idx; vf->lan_vsi_idx = vsi->idx;
vf->lan_vsi_id = vsi->id; vf->lan_vsi_id = vsi->id;
...@@ -696,6 +697,12 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) ...@@ -696,6 +697,12 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
"Could not add MAC filter %pM for VF %d\n", "Could not add MAC filter %pM for VF %d\n",
vf->default_lan_addr.addr, vf->vf_id); vf->default_lan_addr.addr, vf->vf_id);
} }
eth_broadcast_addr(broadcast);
f = i40e_add_filter(vsi, broadcast,
vf->port_vlan_id ? vf->port_vlan_id : -1);
if (!f)
dev_info(&pf->pdev->dev,
"Could not allocate VF broadcast filter\n");
spin_unlock_bh(&vsi->mac_filter_hash_lock); spin_unlock_bh(&vsi->mac_filter_hash_lock);
i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(0, vf->vf_id), i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(0, vf->vf_id),
(u32)hena); (u32)hena);
...@@ -1536,7 +1543,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, ...@@ -1536,7 +1543,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
vf->vf_id, vf->vf_id,
i40e_stat_str(&pf->hw, aq_ret), i40e_stat_str(&pf->hw, aq_ret),
i40e_aq_str(&pf->hw, aq_err)); i40e_aq_str(&pf->hw, aq_err));
goto error_param_int; goto error_param;
} }
} }
...@@ -1581,15 +1588,16 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, ...@@ -1581,15 +1588,16 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
allmulti, NULL, allmulti, NULL,
true); true);
aq_err = pf->hw.aq.asq_last_status; aq_err = pf->hw.aq.asq_last_status;
if (aq_ret) if (aq_ret) {
dev_err(&pf->pdev->dev, dev_err(&pf->pdev->dev,
"VF %d failed to set unicast promiscuous mode %8.8x err %s aq_err %s\n", "VF %d failed to set unicast promiscuous mode %8.8x err %s aq_err %s\n",
vf->vf_id, info->flags, vf->vf_id, info->flags,
i40e_stat_str(&pf->hw, aq_ret), i40e_stat_str(&pf->hw, aq_ret),
i40e_aq_str(&pf->hw, aq_err)); i40e_aq_str(&pf->hw, aq_err));
goto error_param;
}
} }
error_param_int:
if (!aq_ret) { if (!aq_ret) {
dev_info(&pf->pdev->dev, dev_info(&pf->pdev->dev,
"VF %d successfully set unicast promiscuous mode\n", "VF %d successfully set unicast promiscuous mode\n",
......
...@@ -237,6 +237,10 @@ struct i40e_hw_capabilities { ...@@ -237,6 +237,10 @@ struct i40e_hw_capabilities {
#define I40E_NVM_IMAGE_TYPE_UDP_CLOUD 0x3 #define I40E_NVM_IMAGE_TYPE_UDP_CLOUD 0x3
u32 management_mode; u32 management_mode;
u32 mng_protocols_over_mctp;
#define I40E_MNG_PROTOCOL_PLDM 0x2
#define I40E_MNG_PROTOCOL_OEM_COMMANDS 0x4
#define I40E_MNG_PROTOCOL_NCSI 0x8
u32 npar_enable; u32 npar_enable;
u32 os2bmc; u32 os2bmc;
u32 valid_functions; u32 valid_functions;
......
...@@ -207,6 +207,9 @@ static void i40evf_misc_irq_disable(struct i40evf_adapter *adapter) ...@@ -207,6 +207,9 @@ static void i40evf_misc_irq_disable(struct i40evf_adapter *adapter)
{ {
struct i40e_hw *hw = &adapter->hw; struct i40e_hw *hw = &adapter->hw;
if (!adapter->msix_entries)
return;
wr32(hw, I40E_VFINT_DYN_CTL01, 0); wr32(hw, I40E_VFINT_DYN_CTL01, 0);
/* read flush */ /* read flush */
...@@ -631,6 +634,9 @@ static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter) ...@@ -631,6 +634,9 @@ static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter)
{ {
int vector, irq_num, q_vectors; int vector, irq_num, q_vectors;
if (!adapter->msix_entries)
return;
q_vectors = adapter->num_msix_vectors - NONQ_VECS; q_vectors = adapter->num_msix_vectors - NONQ_VECS;
for (vector = 0; vector < q_vectors; vector++) { for (vector = 0; vector < q_vectors; vector++) {
...@@ -651,6 +657,9 @@ static void i40evf_free_misc_irq(struct i40evf_adapter *adapter) ...@@ -651,6 +657,9 @@ static void i40evf_free_misc_irq(struct i40evf_adapter *adapter)
{ {
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
if (!adapter->msix_entries)
return;
free_irq(adapter->msix_entries[0].vector, netdev); free_irq(adapter->msix_entries[0].vector, netdev);
} }
...@@ -1425,6 +1434,9 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter) ...@@ -1425,6 +1434,9 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)
int q_idx, num_q_vectors; int q_idx, num_q_vectors;
int napi_vectors; int napi_vectors;
if (!adapter->q_vectors)
return;
num_q_vectors = adapter->num_msix_vectors - NONQ_VECS; num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
napi_vectors = adapter->num_active_queues; napi_vectors = adapter->num_active_queues;
...@@ -1434,6 +1446,7 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter) ...@@ -1434,6 +1446,7 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)
netif_napi_del(&q_vector->napi); netif_napi_del(&q_vector->napi);
} }
kfree(adapter->q_vectors); kfree(adapter->q_vectors);
adapter->q_vectors = NULL;
} }
/** /**
...@@ -1443,6 +1456,9 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter) ...@@ -1443,6 +1456,9 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)
**/ **/
void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter) void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter)
{ {
if (!adapter->msix_entries)
return;
pci_disable_msix(adapter->pdev); pci_disable_msix(adapter->pdev);
kfree(adapter->msix_entries); kfree(adapter->msix_entries);
adapter->msix_entries = NULL; adapter->msix_entries = NULL;
...@@ -1693,6 +1709,49 @@ static void i40evf_watchdog_task(struct work_struct *work) ...@@ -1693,6 +1709,49 @@ static void i40evf_watchdog_task(struct work_struct *work)
schedule_work(&adapter->adminq_task); schedule_work(&adapter->adminq_task);
} }
static void i40evf_disable_vf(struct i40evf_adapter *adapter)
{
struct i40evf_mac_filter *f, *ftmp;
struct i40evf_vlan_filter *fv, *fvtmp;
adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
if (netif_running(adapter->netdev)) {
set_bit(__I40E_DOWN, &adapter->vsi.state);
netif_carrier_off(adapter->netdev);
netif_tx_disable(adapter->netdev);
adapter->link_up = false;
i40evf_napi_disable_all(adapter);
i40evf_irq_disable(adapter);
i40evf_free_traffic_irqs(adapter);
i40evf_free_all_tx_resources(adapter);
i40evf_free_all_rx_resources(adapter);
}
/* Delete all of the filters, both MAC and VLAN. */
list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
list_del(&f->list);
kfree(f);
}
list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list, list) {
list_del(&fv->list);
kfree(fv);
}
i40evf_free_misc_irq(adapter);
i40evf_reset_interrupt_capability(adapter);
i40evf_free_queues(adapter);
i40evf_free_q_vectors(adapter);
kfree(adapter->vf_res);
i40evf_shutdown_adminq(&adapter->hw);
adapter->netdev->flags &= ~IFF_UP;
clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
adapter->state = __I40EVF_DOWN;
dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n");
}
#define I40EVF_RESET_WAIT_MS 10 #define I40EVF_RESET_WAIT_MS 10
#define I40EVF_RESET_WAIT_COUNT 500 #define I40EVF_RESET_WAIT_COUNT 500
/** /**
...@@ -1758,50 +1817,9 @@ static void i40evf_reset_task(struct work_struct *work) ...@@ -1758,50 +1817,9 @@ static void i40evf_reset_task(struct work_struct *work)
pci_set_master(adapter->pdev); pci_set_master(adapter->pdev);
if (i == I40EVF_RESET_WAIT_COUNT) { if (i == I40EVF_RESET_WAIT_COUNT) {
struct i40evf_mac_filter *ftmp;
struct i40evf_vlan_filter *fv, *fvtmp;
/* reset never finished */
dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n", dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
reg_val); reg_val);
adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED; i40evf_disable_vf(adapter);
if (netif_running(adapter->netdev)) {
set_bit(__I40E_DOWN, &adapter->vsi.state);
netif_carrier_off(netdev);
netif_tx_disable(netdev);
adapter->link_up = false;
i40evf_napi_disable_all(adapter);
i40evf_irq_disable(adapter);
i40evf_free_traffic_irqs(adapter);
i40evf_free_all_tx_resources(adapter);
i40evf_free_all_rx_resources(adapter);
}
/* Delete all of the filters, both MAC and VLAN. */
list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list,
list) {
list_del(&f->list);
kfree(f);
}
list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list,
list) {
list_del(&fv->list);
kfree(fv);
}
i40evf_free_misc_irq(adapter);
i40evf_reset_interrupt_capability(adapter);
i40evf_free_queues(adapter);
i40evf_free_q_vectors(adapter);
kfree(adapter->vf_res);
i40evf_shutdown_adminq(hw);
adapter->netdev->flags &= ~IFF_UP;
clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
adapter->state = __I40EVF_DOWN;
dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n");
return; /* Do not attempt to reinit. It's dead, Jim. */ return; /* Do not attempt to reinit. It's dead, Jim. */
} }
...@@ -2172,6 +2190,64 @@ static int i40evf_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -2172,6 +2190,64 @@ static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)
return 0; return 0;
} }
/**
* i40evf_features_check - Validate encapsulated packet conforms to limits
* @skb: skb buff
* @netdev: This physical port's netdev
* @features: Offload features that the stack believes apply
**/
static netdev_features_t i40evf_features_check(struct sk_buff *skb,
struct net_device *dev,
netdev_features_t features)
{
size_t len;
/* No point in doing any of this if neither checksum nor GSO are
* being requested for this frame. We can rule out both by just
* checking for CHECKSUM_PARTIAL
*/
if (skb->ip_summed != CHECKSUM_PARTIAL)
return features;
/* We cannot support GSO if the MSS is going to be less than
* 64 bytes. If it is then we need to drop support for GSO.
*/
if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
features &= ~NETIF_F_GSO_MASK;
/* MACLEN can support at most 63 words */
len = skb_network_header(skb) - skb->data;
if (len & ~(63 * 2))
goto out_err;
/* IPLEN and EIPLEN can support at most 127 dwords */
len = skb_transport_header(skb) - skb_network_header(skb);
if (len & ~(127 * 4))
goto out_err;
if (skb->encapsulation) {
/* L4TUNLEN can support 127 words */
len = skb_inner_network_header(skb) - skb_transport_header(skb);
if (len & ~(127 * 2))
goto out_err;
/* IPLEN can support at most 127 dwords */
len = skb_inner_transport_header(skb) -
skb_inner_network_header(skb);
if (len & ~(127 * 4))
goto out_err;
}
/* No need to validate L4LEN as TCP is the only protocol with a
* a flexible value and we support all possible values supported
* by TCP, which is at most 15 dwords
*/
return features;
out_err:
return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
}
#define I40EVF_VLAN_FEATURES (NETIF_F_HW_VLAN_CTAG_TX |\ #define I40EVF_VLAN_FEATURES (NETIF_F_HW_VLAN_CTAG_TX |\
NETIF_F_HW_VLAN_CTAG_RX |\ NETIF_F_HW_VLAN_CTAG_RX |\
NETIF_F_HW_VLAN_CTAG_FILTER) NETIF_F_HW_VLAN_CTAG_FILTER)
...@@ -2206,6 +2282,7 @@ static const struct net_device_ops i40evf_netdev_ops = { ...@@ -2206,6 +2282,7 @@ static const struct net_device_ops i40evf_netdev_ops = {
.ndo_tx_timeout = i40evf_tx_timeout, .ndo_tx_timeout = i40evf_tx_timeout,
.ndo_vlan_rx_add_vid = i40evf_vlan_rx_add_vid, .ndo_vlan_rx_add_vid = i40evf_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = i40evf_vlan_rx_kill_vid, .ndo_vlan_rx_kill_vid = i40evf_vlan_rx_kill_vid,
.ndo_features_check = i40evf_features_check,
.ndo_fix_features = i40evf_fix_features, .ndo_fix_features = i40evf_fix_features,
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = i40evf_netpoll, .ndo_poll_controller = i40evf_netpoll,
...@@ -2795,12 +2872,10 @@ static void i40evf_remove(struct pci_dev *pdev) ...@@ -2795,12 +2872,10 @@ static void i40evf_remove(struct pci_dev *pdev)
msleep(50); msleep(50);
} }
if (adapter->msix_entries) {
i40evf_misc_irq_disable(adapter); i40evf_misc_irq_disable(adapter);
i40evf_free_misc_irq(adapter); i40evf_free_misc_irq(adapter);
i40evf_reset_interrupt_capability(adapter); i40evf_reset_interrupt_capability(adapter);
i40evf_free_q_vectors(adapter); i40evf_free_q_vectors(adapter);
}
if (adapter->watchdog_timer.function) if (adapter->watchdog_timer.function)
del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->watchdog_timer);
......
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