From 17413a80bcff78ceb371fb6a34d888780ad7b7fa Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Wed, 4 Jun 2014 01:23:13 +0000 Subject: [PATCH 01/14] i40e: Stop the VF device after setting its MAC address If the host VMM administrator has changed the VF device's MAC address then the i40e driver needs to halt the VF device so that the administrator will be forced to reload the VF driver. This will cause the VF driver to start using the newly assigned MAC address. This brings the i40e driver into conformance with operational characteristics of other Intel SR-IOV featured drivers. Change-ID: Ic7242cceb8287dd2cb72fb1f3166a032a28bf88a Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index f5b9d2062573..d2dabae5b40c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -2077,6 +2077,8 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) } ether_addr_copy(vf->default_lan_addr.addr, mac); vf->pf_set_mac = true; + /* Force the VF driver stop so it has to reload with new MAC address */ + i40e_vc_disable_vf(pf, vf); dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n"); ret = 0; From 23cfbe074da66305d992c663b778d12476eeefce Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 4 Jun 2014 01:23:14 +0000 Subject: [PATCH 02/14] i40e: make prep_for_reset void The return from i40e_prep_for_reset() was being ignored by almost all its callers. The one place it wasn't ignored could have caused a silent and confusing failure of the driver to finish a reset. Since we really are doing a rebuild anyway, ignore this last case as well and simply make the function a void type. Change-ID: Ia4fed7f903d39a6c47c5722625a53e59c3f7ed53 Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b167fc2c4abe..3f60976a0805 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5611,7 +5611,7 @@ static void i40e_fdir_teardown(struct i40e_pf *pf) * * Close up the VFs and other things in prep for pf Reset. **/ -static int i40e_prep_for_reset(struct i40e_pf *pf) +static void i40e_prep_for_reset(struct i40e_pf *pf) { struct i40e_hw *hw = &pf->hw; i40e_status ret = 0; @@ -5619,7 +5619,7 @@ static int i40e_prep_for_reset(struct i40e_pf *pf) clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state); if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) - return 0; + return; dev_dbg(&pf->pdev->dev, "Tearing down internal switch for reset\n"); @@ -5636,13 +5636,10 @@ static int i40e_prep_for_reset(struct i40e_pf *pf) /* call shutdown HMC */ if (hw->hmc.hmc_obj) { ret = i40e_shutdown_lan_hmc(hw); - if (ret) { + if (ret) dev_warn(&pf->pdev->dev, "shutdown_lan_hmc failed: %d\n", ret); - clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state); - } } - return ret; } /** @@ -5816,11 +5813,8 @@ end_core_reset: **/ static void i40e_handle_reset_warning(struct i40e_pf *pf) { - i40e_status ret; - - ret = i40e_prep_for_reset(pf); - if (!ret) - i40e_reset_and_rebuild(pf, false); + i40e_prep_for_reset(pf); + i40e_reset_and_rebuild(pf, false); } /** From df430b1240d3375d053230d1f943383d59f9267a Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Wed, 4 Jun 2014 01:23:15 +0000 Subject: [PATCH 03/14] i40e: Add PF reset when Malicious driver event for PF As per the spec when the PF driver receives a Malicious driver event the queue that caused the event is already stopped and it is expected that the function that owns the queue will reset the queue. In some cases it may not be possible to determine the queue and it is suggested to reset the whole function. This patch takes the later approach when the event is owned by the PF that owns it. Change-ID: I40f9764a6a5e068c0ef8438db00c5aa9c2c6c1c8 Signed-off-by: Neerav Parikh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 3f60976a0805..80c5d55cf50b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5827,6 +5827,7 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf) { struct i40e_hw *hw = &pf->hw; bool mdd_detected = false; + bool pf_mdd_detected = false; struct i40e_vf *vf; u32 reg; int i; @@ -5866,6 +5867,30 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf) mdd_detected = true; } + if (mdd_detected) { + reg = rd32(hw, I40E_PF_MDET_TX); + if (reg & I40E_PF_MDET_TX_VALID_MASK) { + wr32(hw, I40E_PF_MDET_TX, 0xFFFF); + dev_info(&pf->pdev->dev, + "MDD TX event is for this function 0x%08x, requesting PF reset.\n", + reg); + pf_mdd_detected = true; + } + reg = rd32(hw, I40E_PF_MDET_RX); + if (reg & I40E_PF_MDET_RX_VALID_MASK) { + wr32(hw, I40E_PF_MDET_RX, 0xFFFF); + dev_info(&pf->pdev->dev, + "MDD RX event is for this function 0x%08x, requesting PF reset.\n", + reg); + pf_mdd_detected = true; + } + /* Queue belongs to the PF, initiate a reset */ + if (pf_mdd_detected) { + set_bit(__I40E_PF_RESET_REQUESTED, &pf->state); + i40e_service_event_schedule(pf); + } + } + /* see if one of the VFs needs its hand slapped */ for (i = 0; i < pf->num_alloc_vfs && mdd_detected; i++) { vf = &(pf->vf[i]); From 278b6f629c8221b06850f43c748d0888d5d15a24 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 4 Jun 2014 01:41:03 +0000 Subject: [PATCH 04/14] i40e: warn on newer/older firmware API rev If the firmware's API minor number is larger than the one expected, log a warning and recommend driver SW update. If the firmware's API major or minor number is smaller then the one expected (n for major, n or n-1 for minor), log a warning and recommend NVM update. Change-ID: If0b887e055478f8e435ba7fa28113b63a6f1bb35 Signed-off-by: Shannon Nelson Signed-off-by: Catherine Sullivan Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 80c5d55cf50b..4289ff1e84ef 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8633,6 +8633,20 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_pf_reset; } + if (hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR) + dev_info(&pdev->dev, + "Note: FW API version %02x.%02x newer than expected %02x.%02x, recommend driver update.\n", + hw->aq.api_maj_ver, hw->aq.api_min_ver, + I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR); + + if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR || + hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR-1)) + dev_info(&pdev->dev, + "Note: FW API version %02x.%02x older than expected %02x.%02x, recommend nvm update.\n", + hw->aq.api_maj_ver, hw->aq.api_min_ver, + I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR); + + i40e_verify_eeprom(pf); /* Rev 0 hardware was never productized */ From cde4cbc7800469c9b8424261b69c45a71a89caf4 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 4 Jun 2014 01:23:17 +0000 Subject: [PATCH 05/14] i40e: fix a stray print message This log print message will probably never be seen, but it needs to match the "attempting to rebuild switch\n" log message a few lines above. Change-ID: Ic3f5b4f67568d721cb02e826cf2cb33847f51c11 Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 4289ff1e84ef..b4278a22382c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5775,7 +5775,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) } if (pf->vsi[pf->lan_vsi]->uplink_seid == pf->mac_seid) { - dev_info(&pf->pdev->dev, "attempting to rebuild PF VSI\n"); + dev_dbg(&pf->pdev->dev, "attempting to rebuild PF VSI\n"); /* no VEB, so rebuild only the Main VSI */ ret = i40e_add_vsi(pf->vsi[pf->lan_vsi]); if (ret) { From 5c2cebda438b888147f6dfd6d1423432d837c0ea Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Wed, 4 Jun 2014 01:23:18 +0000 Subject: [PATCH 06/14] i40e: Fix ethtool coalesce settings This patch fixes the i40e_set_coalesce function to allow 0 as a disable value. Also, added message to user about invalid value and provides valid range. Change-ID: I6c9ff11a9861f2045bd543745a3d132999ffbbd8 Signed-off-by: Carolyn Wyborny Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + .../net/ethernet/intel/i40e/i40e_ethtool.c | 28 +++++++++++++++---- drivers/net/ethernet/intel/i40e/i40e_main.c | 16 +++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 817e179dc3f9..07811dd6eb89 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -617,6 +617,7 @@ static inline void i40e_dbg_init(void) {} static inline void i40e_dbg_exit(void) {} #endif /* CONFIG_DEBUG_FS*/ void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector); +void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector); void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf); void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf); int i40e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 4a488ffcd6b0..7da37581bc02 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1105,17 +1105,36 @@ static int i40e_set_coalesce(struct net_device *netdev, if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq) vsi->work_limit = ec->tx_max_coalesced_frames_irq; + vector = vsi->base_vector; if ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) && - (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1))) + (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1))) { vsi->rx_itr_setting = ec->rx_coalesce_usecs; - else + } else if (ec->rx_coalesce_usecs == 0) { + vsi->rx_itr_setting = ec->rx_coalesce_usecs; + i40e_irq_dynamic_disable(vsi, vector); + if (ec->use_adaptive_rx_coalesce) + netif_info(pf, drv, netdev, + "Rx-secs=0, need to disable adaptive-Rx for a complete disable\n"); + } else { + netif_info(pf, drv, netdev, + "Invalid value, Rx-usecs range is 0, 8-8160\n"); return -EINVAL; + } if ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) && - (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1))) + (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1))) { vsi->tx_itr_setting = ec->tx_coalesce_usecs; - else + } else if (ec->tx_coalesce_usecs == 0) { + vsi->tx_itr_setting = ec->tx_coalesce_usecs; + i40e_irq_dynamic_disable(vsi, vector); + if (ec->use_adaptive_tx_coalesce) + netif_info(pf, drv, netdev, + "Tx-secs=0, need to disable adaptive-Tx for a complete disable\n"); + } else { + netif_info(pf, drv, netdev, + "Invalid value, Tx-usecs range is 0, 8-8160\n"); return -EINVAL; + } if (ec->use_adaptive_rx_coalesce) vsi->rx_itr_setting |= I40E_ITR_DYNAMIC; @@ -1127,7 +1146,6 @@ static int i40e_set_coalesce(struct net_device *netdev, else vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC; - vector = vsi->base_vector; for (i = 0; i < vsi->num_q_vectors; i++, vector++) { q_vector = vsi->q_vectors[i]; q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b4278a22382c..71efc68c5d99 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2767,6 +2767,22 @@ void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector) /* skip the flush */ } +/** + * i40e_irq_dynamic_disable - Disable default interrupt generation settings + * @vsi: pointer to a vsi + * @vector: enable a particular Hw Interrupt vector + **/ +void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector) +{ + struct i40e_pf *pf = vsi->back; + struct i40e_hw *hw = &pf->hw; + u32 val; + + val = I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT; + wr32(hw, I40E_PFINT_DYN_CTLN(vector - 1), val); + i40e_flush(hw); +} + /** * i40e_msix_clean_rings - MSIX mode Interrupt Handler * @irq: interrupt number From c571ea05a03da856b1e9f8c0355128a7044d6a91 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 4 Jun 2014 01:23:19 +0000 Subject: [PATCH 07/14] i40e/i40evf: remove reserved type One of the PCTYPES that was moved to a reserved value wasn't removed from the code. Change-ID: I31fafe6d79c5f5128179979af5eaafa8c0cd62fe Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 - drivers/net/ethernet/intel/i40e/i40e_type.h | 1 - drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 1 - drivers/net/ethernet/intel/i40evf/i40e_type.h | 1 - 4 files changed, 4 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 0277894fe1c4..f09fb3ef691d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -75,7 +75,6 @@ enum i40e_dyn_idx_t { ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \ ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | \ ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \ - ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | \ ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \ ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \ ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \ diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 1c0d5a70b892..11dd2dcfb592 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -878,7 +878,6 @@ enum i40e_filter_pctype { I40E_FILTER_PCTYPE_FRAG_IPV4 = 36, /* Note: Values 37-40 are reserved for future use */ I40E_FILTER_PCTYPE_NONF_IPV6_UDP = 41, - I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN = 42, I40E_FILTER_PCTYPE_NONF_IPV6_TCP = 43, I40E_FILTER_PCTYPE_NONF_IPV6_SCTP = 44, I40E_FILTER_PCTYPE_NONF_IPV6_OTHER = 45, diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index 30d248bc5d19..acd3c12b8f6a 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -75,7 +75,6 @@ enum i40e_dyn_idx_t { ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \ ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | \ ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \ - ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | \ ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \ ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \ ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 9c835786e8a1..23cd18b66b71 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -878,7 +878,6 @@ enum i40e_filter_pctype { I40E_FILTER_PCTYPE_FRAG_IPV4 = 36, /* Note: Values 37-40 are reserved for future use */ I40E_FILTER_PCTYPE_NONF_IPV6_UDP = 41, - I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN = 42, I40E_FILTER_PCTYPE_NONF_IPV6_TCP = 43, I40E_FILTER_PCTYPE_NONF_IPV6_SCTP = 44, I40E_FILTER_PCTYPE_NONF_IPV6_OTHER = 45, From 1ac978af7caca1aa857802822602520a58a50018 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Wed, 4 Jun 2014 01:23:20 +0000 Subject: [PATCH 08/14] i40e: Add ablitity to enable/disable link from set_link_restart_an The ability is already there in the fw and this will make it easy to toggle link without calling set_phy_config when no other link settings need to change. Change-ID: I185567ae81776382ac145247e4eb1ee95f22382c Signed-off-by: Catherine Sullivan Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 8 +++++++- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 3 ++- drivers/net/ethernet/intel/i40e/i40e_prototype.h | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index a51bba634718..bbace40bd114 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -971,12 +971,14 @@ i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw, /** * i40e_aq_set_link_restart_an * @hw: pointer to the hw struct + * @enable_link: if true: enable link, if false: disable link * @cmd_details: pointer to command details structure or NULL * * Sets up the link and restarts the Auto-Negotiation over the link. **/ i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw, - struct i40e_asq_cmd_details *cmd_details) + bool enable_link, + struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_set_link_restart_an *cmd = @@ -987,6 +989,10 @@ i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw, i40e_aqc_opc_set_link_restart_an); cmd->command = I40E_AQ_PHY_RESTART_AN; + if (enable_link) + cmd->command |= I40E_AQ_PHY_LINK_ENABLE; + else + cmd->command &= ~I40E_AQ_PHY_LINK_ENABLE; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 7da37581bc02..df89b6c3db41 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1027,9 +1027,10 @@ static int i40e_nway_reset(struct net_device *netdev) struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; struct i40e_hw *hw = &pf->hw; + bool link_up = hw->phy.link_info.link_info & I40E_AQ_LINK_UP; i40e_status ret = 0; - ret = i40e_aq_set_link_restart_an(hw, NULL); + ret = i40e_aq_set_link_restart_an(hw, link_up, NULL); if (ret) { netdev_info(netdev, "link restart failed, aq_err=%d\n", pf->hw.aq.asq_last_status); diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index a430699c41d5..3300b996a467 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -77,7 +77,8 @@ i40e_status i40e_aq_set_default_vsi(struct i40e_hw *hw, u16 vsi_id, i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw, - struct i40e_asq_cmd_details *cmd_details); + bool enable_link, + struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_get_link_info(struct i40e_hw *hw, bool enable_lse, struct i40e_link_status *link, struct i40e_asq_cmd_details *cmd_details); From cc41222c55e9ec44d148dee67e6ad407e3b79e46 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 4 Jun 2014 01:23:21 +0000 Subject: [PATCH 09/14] i40e: use WoL flag when setting LAA Make sure the Firmware sets up the LAA as a Wake-On-LAN address. Change-ID: I57b9acd8c288424fcfed0911053eb725c400b41c Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 71efc68c5d99..44789c2e3f50 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1337,7 +1337,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p) if (vsi->type == I40E_VSI_MAIN) { i40e_status ret; ret = i40e_aq_mac_address_write(&vsi->back->hw, - I40E_AQC_WRITE_TYPE_LAA_ONLY, + I40E_AQC_WRITE_TYPE_LAA_WOL, addr->sa_data, NULL); if (ret) { netdev_info(netdev, From 6c8ad1ba1650e6c22dcaa5fe288c6236c3b25ae5 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 4 Jun 2014 01:23:22 +0000 Subject: [PATCH 10/14] i40e: allow user to set LAA again Don't short-circuit the LAA assignment when the driver thinks it has already been done - it is possible that the user might want to force the address setting again. At the same time, this requires a little re-ordering of the filter management. Change-ID: Ia0d71e3bc04edd7b68cf67edecc00abe7b9f6639 Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 31 +++++++++++---------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 44789c2e3f50..81cbea72722e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1327,9 +1327,6 @@ static int i40e_set_mac(struct net_device *netdev, void *p) netdev_info(netdev, "set mac address=%pM\n", addr->sa_data); - if (ether_addr_equal(netdev->dev_addr, addr->sa_data)) - return 0; - if (test_bit(__I40E_DOWN, &vsi->back->state) || test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) return -EADDRNOTAVAIL; @@ -1345,22 +1342,26 @@ static int i40e_set_mac(struct net_device *netdev, void *p) ret); return -EADDRNOTAVAIL; } - - ether_addr_copy(vsi->back->hw.mac.addr, addr->sa_data); } - /* In order to be sure to not drop any packets, add the new address - * then delete the old one. - */ - f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY, false, false); - if (!f) - return -ENOMEM; + if (!i40e_find_mac(vsi, addr->sa_data, false, true)) { - i40e_sync_vsi_filters(vsi); - i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY, false, false); - i40e_sync_vsi_filters(vsi); + /* In order to be sure to not drop any packets, add the + * new address first then delete the old one. + */ + f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY, + false, false); + if (!f) + return -ENOMEM; - ether_addr_copy(netdev->dev_addr, addr->sa_data); + i40e_sync_vsi_filters(vsi); + i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY, + false, false); + i40e_sync_vsi_filters(vsi); + } + + if (!ether_addr_equal(netdev->dev_addr, addr->sa_data)) + ether_addr_copy(netdev->dev_addr, addr->sa_data); return 0; } From 6252c7e4ee48f016dd075168df9fabc7197f38e5 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 4 Jun 2014 01:23:23 +0000 Subject: [PATCH 11/14] i40e: reapply LAA after reset The LAA is lost on a reset, so be sure to replay it when rebuilding the switch after any reset. Change-ID: I6e643f9a59dfd899b6cbdf84d93b4bc9c37bb949 Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 07811dd6eb89..2ec6e8a11ee1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -362,6 +362,7 @@ struct i40e_mac_filter { bool is_vf; /* filter belongs to a VF */ bool is_netdev; /* filter belongs to a netdev */ bool changed; /* filter needs to be sync'd to the HW */ + bool is_laa; /* filter is a Locally Administered Address */ }; struct i40e_veb { diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 81cbea72722e..9276ca3f43f2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1344,8 +1344,8 @@ static int i40e_set_mac(struct net_device *netdev, void *p) } } - if (!i40e_find_mac(vsi, addr->sa_data, false, true)) { - + f = i40e_find_mac(vsi, addr->sa_data, false, true); + if (!f) { /* In order to be sure to not drop any packets, add the * new address first then delete the old one. */ @@ -1360,6 +1360,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p) i40e_sync_vsi_filters(vsi); } + f->is_laa = true; if (!ether_addr_equal(netdev->dev_addr, addr->sa_data)) ether_addr_copy(netdev->dev_addr, addr->sa_data); @@ -7378,6 +7379,12 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { f->changed = true; f_count++; + + if (f->is_laa && vsi->type == I40E_VSI_MAIN) { + i40e_aq_mac_address_write(&vsi->back->hw, + I40E_AQC_WRITE_TYPE_LAA_WOL, + f->macaddr, NULL); + } } if (f_count) { vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; From 264ccc93b23ae654d3db37c3ebde1da6a2866e31 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 4 Jun 2014 01:23:24 +0000 Subject: [PATCH 12/14] i40e: no pf reset at pci remove The PF reset to clean up at the end of the remove is a nice thing to do, but it also removes any LAA setting that Wake On LAN wants for future wake up. Change-ID: Ic090ec714df2d722281d11735cf75f2aa4432e2c Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 9276ca3f43f2..e2dbe0427cdf 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8898,7 +8898,6 @@ static void i40e_remove(struct pci_dev *pdev) { struct i40e_pf *pf = pci_get_drvdata(pdev); i40e_status ret_code; - u32 reg; int i; i40e_dbg_pf_exit(pf); @@ -8976,11 +8975,6 @@ static void i40e_remove(struct pci_dev *pdev) kfree(pf->irq_pile); kfree(pf->vsi); - /* force a PF reset to clean anything leftover */ - reg = rd32(&pf->hw, I40E_PFGEN_CTRL); - wr32(&pf->hw, I40E_PFGEN_CTRL, (reg | I40E_PFGEN_CTRL_PFSWR_MASK)); - i40e_flush(&pf->hw); - iounmap(pf->hw.hw_addr); kfree(pf); pci_release_selected_regions(pdev, From 327fe04bfb32642eee237e1cc1eaef16d6a4a0f5 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Wed, 4 Jun 2014 01:23:26 +0000 Subject: [PATCH 13/14] i40e: Bypass timeout recovery level 0 so as to not cause MDD When a Tx hang happens, usually the Tx queue disable fails. At this point if we try to recover by a VSI reinit the HW gets unhappy and we get a Malicious Driver Detect (MDD) event. HW expects a PF reset if a queue disable fails, if we don't do a PF reset and restart the queue we get an MDD. This patch makes sure we do a PF reset on Tx hang and that way we avoid any MDD because of Tx queue disable failure. Change-ID: I665ab6223577c788da857ee2132e733dc9a451e4 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index e2dbe0427cdf..50f9ab72c95f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -278,7 +278,7 @@ static void i40e_tx_timeout(struct net_device *netdev) pf->tx_timeout_count++; if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ*20))) - pf->tx_timeout_recovery_level = 0; + pf->tx_timeout_recovery_level = 1; pf->tx_timeout_last_recovery = jiffies; netdev_info(netdev, "tx_timeout recovery level %d\n", pf->tx_timeout_recovery_level); @@ -6826,6 +6826,8 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->irq_pile->num_entries = pf->hw.func_caps.num_msix_vectors; pf->irq_pile->search_hint = 0; + pf->tx_timeout_recovery_level = 1; + mutex_init(&pf->switch_mutex); sw_init_done: From 25941f94ba2dbb0b8e451a917aa12a547994c738 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Wed, 4 Jun 2014 01:23:27 +0000 Subject: [PATCH 14/14] i40e/i40evf: Bump i40e to 0.4.17 and i40evf to 0.9.36 Bump versions. Change-ID: I47fc3433240800cd823ff512f3015822277b0d20 Signed-off-by: Catherine Sullivan Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 50f9ab72c95f..5980d6b3fb1a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -39,7 +39,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 0 #define DRV_VERSION_MINOR 4 -#define DRV_VERSION_BUILD 13 +#define DRV_VERSION_BUILD 17 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 2fdccce1b872..b473172708f5 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -36,7 +36,7 @@ char i40evf_driver_name[] = "i40evf"; static const char i40evf_driver_string[] = "Intel(R) XL710 X710 Virtual Function Network Driver"; -#define DRV_VERSION "0.9.35" +#define DRV_VERSION "0.9.36" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2014 Intel Corporation.";