From 3d72aebfc61b025a2478c9d2bbc3c8c4036a1c05 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 27 Oct 2017 11:06:55 -0400 Subject: i40e: Fix for NUP NVM image downgrade failure Since commit 96a39aed25e6 ("i40e: Acquire NVM lock before reads on all devices") we've used the NVM lock to synchronize NVM reads even on devices which don't strictly need the lock. Doing so can cause a regression on older firmware prior to 1.5, especially when downgrading the firmware. Fix this by only grabbing the lock if we're running on an X722 device (which requires the lock as it uses the AdminQ to read the NVM), or if we're currently running 1.5 or newer firmware. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 6 ++++++ drivers/net/ethernet/intel/i40e/i40e_common.c | 3 ++- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 8 +++++--- drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + 4 files changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 9dcb2a961197..9af74253c3f7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -613,6 +613,12 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw) hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE; } + /* Newer versions of firmware require lock when reading the NVM */ + if (hw->aq.api_maj_ver > 1 || + (hw->aq.api_maj_ver == 1 && + hw->aq.api_min_ver >= 5)) + hw->flags |= I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK; + /* 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 && diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 0203665cb53c..13c79468a6da 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -948,7 +948,8 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw) hw->pf_id = (u8)(func_rid & 0x7); if (hw->mac.type == I40E_MAC_X722) - hw->flags |= I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE; + hw->flags |= I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE | + I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK; status = i40e_init_nvm(hw); return status; diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 0ccab0a5d717..7689c2ee0d46 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -328,15 +328,17 @@ static i40e_status __i40e_read_nvm_word(struct i40e_hw *hw, i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, u16 *data) { - i40e_status ret_code; + i40e_status ret_code = 0; - ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); + if (hw->flags & I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK) + ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); if (ret_code) return ret_code; ret_code = __i40e_read_nvm_word(hw, offset, data); - i40e_release_nvm(hw); + if (hw->flags & I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK) + i40e_release_nvm(hw); return ret_code; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 00d4833e9925..0e8568719b4e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -629,6 +629,7 @@ struct i40e_hw { #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) +#define I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK BIT_ULL(3) u64 flags; /* Used in set switch config AQ command */ -- cgit v1.2.3-58-ga151 From 34c164de5867659f9162ae4fc9030b940bd40aaa Mon Sep 17 00:00:00 2001 From: Zijie Pan Date: Tue, 7 Nov 2017 12:06:07 -0800 Subject: i40e: fix the calculation of VFs mac addresses num_mac should be increased only after the call to i40e_add_mac_filter(). Fixes: 5f527ba962e2 ("i40e: Limit the number of MAC and VLAN addresses that can be added for VFs") Signed-off-by: Zijie Pan Signed-off-by: Nicolas Dichtel Reviewed-by: Tushar Dave Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index f8a794b72462..a3dc9b932946 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -2218,18 +2218,19 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) struct i40e_mac_filter *f; f = i40e_find_mac(vsi, al->list[i].addr); - if (!f) + if (!f) { f = i40e_add_mac_filter(vsi, al->list[i].addr); - if (!f) { - dev_err(&pf->pdev->dev, - "Unable to add MAC filter %pM for VF %d\n", - al->list[i].addr, vf->vf_id); - ret = I40E_ERR_PARAM; - spin_unlock_bh(&vsi->mac_filter_hash_lock); - goto error_param; - } else { - vf->num_mac++; + if (!f) { + dev_err(&pf->pdev->dev, + "Unable to add MAC filter %pM for VF %d\n", + al->list[i].addr, vf->vf_id); + ret = I40E_ERR_PARAM; + spin_unlock_bh(&vsi->mac_filter_hash_lock); + goto error_param; + } else { + vf->num_mac++; + } } } spin_unlock_bh(&vsi->mac_filter_hash_lock); -- cgit v1.2.3-58-ga151 From e56afa599609d3afe8b0ce24b553ab95e9782502 Mon Sep 17 00:00:00 2001 From: Amritha Nambiar Date: Wed, 8 Nov 2017 16:38:43 -0800 Subject: i40e: Remove limit of 64 max queues per channel It is safe to remove the upper limit of 64 queues on a channel VSI. The upper bound is determined by the VSI's num_queue_pairs and gets validated when the queue mapping info through mqprio interface is subject to bound checking in the driver. Signed-off-by: Amritha Nambiar Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 - drivers/net/ethernet/intel/i40e/i40e_main.c | 8 -------- 2 files changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 5829715fa342..e019baa905c5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -90,7 +90,6 @@ #define I40E_AQ_LEN 256 #define I40E_AQ_WORK_LIMIT 66 /* max number of VFs + a little */ #define I40E_MAX_USER_PRIORITY 8 -#define I40E_MAX_QUEUES_PER_CH 64 #define I40E_DEFAULT_TRAFFIC_CLASS BIT(0) #define I40E_DEFAULT_MSG_ENABLE 4 #define I40E_QUEUE_WAIT_RETRY_LIMIT 10 diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 4a964d6e4a9e..173e924d4dae 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5629,14 +5629,6 @@ static int i40e_validate_num_queues(struct i40e_pf *pf, int num_queues, return -EINVAL; *reconfig_rss = false; - - if (num_queues > I40E_MAX_QUEUES_PER_CH) { - dev_err(&pf->pdev->dev, - "Failed to create VMDq VSI. User requested num_queues (%d) > I40E_MAX_QUEUES_PER_VSI (%u)\n", - num_queues, I40E_MAX_QUEUES_PER_CH); - return -EINVAL; - } - if (vsi->current_rss_size) { if (num_queues > vsi->current_rss_size) { dev_dbg(&pf->pdev->dev, -- cgit v1.2.3-58-ga151 From 94075bb1ed7c89cdf4c46eca3938ac4f087827af Mon Sep 17 00:00:00 2001 From: Filip Sadowski Date: Tue, 14 Nov 2017 07:00:49 -0500 Subject: i40e: Fix FLR reset timeout issue This patch allows detection of upcoming core reset in case NIC gets stuck while performing FLR reset. The i40e_pf_reset() function returns I40E_ERR_NOT_READY when global reset was detected. Signed-off-by: Filip Sadowski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 13c79468a6da..095965f268bd 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1269,6 +1269,7 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw) * we don't need to do the PF Reset */ if (!cnt) { + u32 reg2 = 0; if (hw->revision_id == 0) cnt = I40E_PF_RESET_WAIT_COUNT_A0; else @@ -1280,6 +1281,12 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw) reg = rd32(hw, I40E_PFGEN_CTRL); if (!(reg & I40E_PFGEN_CTRL_PFSWR_MASK)) break; + reg2 = rd32(hw, I40E_GLGEN_RSTAT); + if (reg2 & I40E_GLGEN_RSTAT_DEVSTATE_MASK) { + hw_dbg(hw, "Core reset upcoming. Skipping PF reset request.\n"); + hw_dbg(hw, "I40E_GLGEN_RSTAT = 0x%x\n", reg2); + return I40E_ERR_NOT_READY; + } usleep_range(1000, 2000); } if (reg & I40E_PFGEN_CTRL_PFSWR_MASK) { -- cgit v1.2.3-58-ga151 From 01acc73f375ed535fa048a9e7f40ed109f7f0276 Mon Sep 17 00:00:00 2001 From: Alan Brady Date: Tue, 14 Nov 2017 07:00:51 -0500 Subject: i40evf: fix client notify of l2 params The current method for notifying clients of l2 parameters is broken because we fail to copy the new parameters to the client instance struct, we need to do the notification before the client 'open' function pointer gets called, and lastly we should set the l2 parameters when first adding a client instance. This patch first introduces the i40evf_client_get_params function to prevent code duplication in the i40evf_client_add_instance and the i40evf_notify_client_l2_params functions. We then fix the notify l2 params function to actually copy the parameters to client instance struct and do the same in the *_add_instance' function. Lastly this patch reorganizes the priority in which client tasks fire so that if the flag for notifying l2 params is set, it will trigger before the open because the client needs these new parameters as part of a client open task. Signed-off-by: Alan Brady Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_client.c | 38 ++++++++++++++++------- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 10 +++--- 2 files changed, 31 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_client.c b/drivers/net/ethernet/intel/i40evf/i40evf_client.c index d8131139565e..da60ce12b33d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_client.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_client.c @@ -25,6 +25,26 @@ static struct i40e_ops i40evf_lan_ops = { .setup_qvlist = i40evf_client_setup_qvlist, }; +/** + * i40evf_client_get_params - retrieve relevant client parameters + * @vsi: VSI with parameters + * @params: client param struct + **/ +static +void i40evf_client_get_params(struct i40e_vsi *vsi, struct i40e_params *params) +{ + int i; + + memset(params, 0, sizeof(struct i40e_params)); + params->mtu = vsi->netdev->mtu; + params->link_up = vsi->back->link_up; + + for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { + params->qos.prio_qos[i].tc = 0; + params->qos.prio_qos[i].qs_handle = vsi->qs_handle; + } +} + /** * i40evf_notify_client_message - call the client message receive callback * @vsi: the VSI associated with this client @@ -66,10 +86,6 @@ void i40evf_notify_client_l2_params(struct i40e_vsi *vsi) return; cinst = vsi->back->cinst; - memset(¶ms, 0, sizeof(params)); - params.mtu = vsi->netdev->mtu; - params.link_up = vsi->back->link_up; - params.qos.prio_qos[0].qs_handle = vsi->qs_handle; if (!cinst || !cinst->client || !cinst->client->ops || !cinst->client->ops->l2_param_change) { @@ -77,6 +93,8 @@ void i40evf_notify_client_l2_params(struct i40e_vsi *vsi) "Cannot locate client instance l2_param_change function\n"); return; } + i40evf_client_get_params(vsi, ¶ms); + cinst->lan_info.params = params; cinst->client->ops->l2_param_change(&cinst->lan_info, cinst->client, ¶ms); } @@ -166,9 +184,9 @@ static struct i40e_client_instance * i40evf_client_add_instance(struct i40evf_adapter *adapter) { struct i40e_client_instance *cinst = NULL; - struct netdev_hw_addr *mac = NULL; struct i40e_vsi *vsi = &adapter->vsi; - int i; + struct netdev_hw_addr *mac = NULL; + struct i40e_params params; if (!vf_registered_client) goto out; @@ -192,18 +210,14 @@ i40evf_client_add_instance(struct i40evf_adapter *adapter) cinst->lan_info.version.major = I40EVF_CLIENT_VERSION_MAJOR; cinst->lan_info.version.minor = I40EVF_CLIENT_VERSION_MINOR; cinst->lan_info.version.build = I40EVF_CLIENT_VERSION_BUILD; + i40evf_client_get_params(vsi, ¶ms); + cinst->lan_info.params = params; set_bit(__I40E_CLIENT_INSTANCE_NONE, &cinst->state); cinst->lan_info.msix_count = adapter->num_iwarp_msix; cinst->lan_info.msix_entries = &adapter->msix_entries[adapter->iwarp_base_vector]; - for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { - cinst->lan_info.params.qos.prio_qos[i].tc = 0; - cinst->lan_info.params.qos.prio_qos[i].qs_handle = - vsi->qs_handle; - } - mac = list_first_entry(&cinst->lan_info.netdev->dev_addrs.list, struct netdev_hw_addr, list); if (mac) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index ca2ebdbd24d7..7b2a4eba92e2 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2110,6 +2110,11 @@ static void i40evf_client_task(struct work_struct *work) adapter->flags &= ~I40EVF_FLAG_SERVICE_CLIENT_REQUESTED; goto out; } + if (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS) { + i40evf_notify_client_l2_params(&adapter->vsi); + adapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS; + goto out; + } if (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_CLOSE) { i40evf_notify_client_close(&adapter->vsi, false); adapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_CLOSE; @@ -2118,11 +2123,6 @@ static void i40evf_client_task(struct work_struct *work) if (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_OPEN) { i40evf_notify_client_open(&adapter->vsi); adapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_OPEN; - goto out; - } - if (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS) { - i40evf_notify_client_l2_params(&adapter->vsi); - adapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS; } out: clear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section); -- cgit v1.2.3-58-ga151 From bd5608b3223bc711a5b365f80d4e67866ac7cc44 Mon Sep 17 00:00:00 2001 From: Alan Brady Date: Tue, 14 Nov 2017 07:00:52 -0500 Subject: i40e: restore promiscuous after reset After a reset we rebuild the VSIs which is going to clobber any promiscuous settings we had before reset. This makes it so that we restore the promiscuous settings we had before reset. Signed-off-by: Alan Brady Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 155 +++++++++++++++------------- 1 file changed, 83 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 173e924d4dae..775d5a125887 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2166,6 +2166,73 @@ i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name, return aq_ret; } +/** + * i40e_set_promiscuous - set promiscuous mode + * @pf: board private structure + * @promisc: promisc on or off + * + * There are different ways of setting promiscuous mode on a PF depending on + * what state/environment we're in. This identifies and sets it appropriately. + * Returns 0 on success. + **/ +static int i40e_set_promiscuous(struct i40e_pf *pf, bool promisc) +{ + struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; + struct i40e_hw *hw = &pf->hw; + i40e_status aq_ret; + + if (vsi->type == I40E_VSI_MAIN && + pf->lan_veb != I40E_NO_VEB && + !(pf->flags & I40E_FLAG_MFP_ENABLED)) { + /* set defport ON for Main VSI instead of true promisc + * this way we will get all unicast/multicast and VLAN + * promisc behavior but will not get VF or VMDq traffic + * replicated on the Main VSI. + */ + if (promisc) + aq_ret = i40e_aq_set_default_vsi(hw, + vsi->seid, + NULL); + else + aq_ret = i40e_aq_clear_default_vsi(hw, + vsi->seid, + NULL); + if (aq_ret) { + dev_info(&pf->pdev->dev, + "Set default VSI failed, err %s, aq_err %s\n", + i40e_stat_str(hw, aq_ret), + i40e_aq_str(hw, hw->aq.asq_last_status)); + } + } else { + aq_ret = i40e_aq_set_vsi_unicast_promiscuous( + hw, + vsi->seid, + promisc, NULL, + true); + if (aq_ret) { + dev_info(&pf->pdev->dev, + "set unicast promisc failed, err %s, aq_err %s\n", + i40e_stat_str(hw, aq_ret), + i40e_aq_str(hw, hw->aq.asq_last_status)); + } + aq_ret = i40e_aq_set_vsi_multicast_promiscuous( + hw, + vsi->seid, + promisc, NULL); + if (aq_ret) { + dev_info(&pf->pdev->dev, + "set multicast promisc failed, err %s, aq_err %s\n", + i40e_stat_str(hw, aq_ret), + i40e_aq_str(hw, hw->aq.asq_last_status)); + } + } + + if (!aq_ret) + pf->cur_promisc = promisc; + + return aq_ret; +} + /** * i40e_sync_vsi_filters - Update the VSI filter list to the HW * @vsi: ptr to the VSI @@ -2467,81 +2534,16 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) cur_promisc = (!!(vsi->current_netdev_flags & IFF_PROMISC) || test_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state)); - if ((vsi->type == I40E_VSI_MAIN) && - (pf->lan_veb != I40E_NO_VEB) && - !(pf->flags & I40E_FLAG_MFP_ENABLED)) { - /* set defport ON for Main VSI instead of true promisc - * this way we will get all unicast/multicast and VLAN - * promisc behavior but will not get VF or VMDq traffic - * replicated on the Main VSI. - */ - if (pf->cur_promisc != cur_promisc) { - pf->cur_promisc = cur_promisc; - if (cur_promisc) - aq_ret = - i40e_aq_set_default_vsi(hw, - vsi->seid, - NULL); - else - aq_ret = - i40e_aq_clear_default_vsi(hw, - vsi->seid, - NULL); - if (aq_ret) { - retval = i40e_aq_rc_to_posix(aq_ret, - hw->aq.asq_last_status); - dev_info(&pf->pdev->dev, - "Set default VSI failed on %s, err %s, aq_err %s\n", - vsi_name, - i40e_stat_str(hw, aq_ret), - i40e_aq_str(hw, - hw->aq.asq_last_status)); - } - } - } else { - aq_ret = i40e_aq_set_vsi_unicast_promiscuous( - hw, - vsi->seid, - cur_promisc, NULL, - true); - if (aq_ret) { - retval = - i40e_aq_rc_to_posix(aq_ret, - hw->aq.asq_last_status); - dev_info(&pf->pdev->dev, - "set unicast promisc failed on %s, err %s, aq_err %s\n", - vsi_name, - i40e_stat_str(hw, aq_ret), - i40e_aq_str(hw, - hw->aq.asq_last_status)); - } - aq_ret = i40e_aq_set_vsi_multicast_promiscuous( - hw, - vsi->seid, - cur_promisc, NULL); - if (aq_ret) { - retval = - i40e_aq_rc_to_posix(aq_ret, - hw->aq.asq_last_status); - dev_info(&pf->pdev->dev, - "set multicast promisc failed on %s, err %s, aq_err %s\n", - vsi_name, - i40e_stat_str(hw, aq_ret), - i40e_aq_str(hw, - hw->aq.asq_last_status)); - } - } - aq_ret = i40e_aq_set_vsi_broadcast(&vsi->back->hw, - vsi->seid, - cur_promisc, NULL); + aq_ret = i40e_set_promiscuous(pf, cur_promisc); if (aq_ret) { retval = i40e_aq_rc_to_posix(aq_ret, - pf->hw.aq.asq_last_status); + 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)); + "Setting promiscuous %s failed on %s, err %s aq_err %s\n", + cur_promisc ? "on" : "off", + vsi_name, + i40e_stat_str(hw, aq_ret), + i40e_aq_str(hw, hw->aq.asq_last_status)); } } out: @@ -9421,6 +9423,15 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) if (!lock_acquired) rtnl_unlock(); + /* Restore promiscuous settings */ + ret = i40e_set_promiscuous(pf, pf->cur_promisc); + if (ret) + dev_warn(&pf->pdev->dev, + "Failed to restore promiscuous setting: %s, err %s aq_err %s\n", + pf->cur_promisc ? "on" : "off", + i40e_stat_str(&pf->hw, ret), + i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); + i40e_reset_all_vfs(pf, true); /* tell the firmware that we're starting */ -- cgit v1.2.3-58-ga151 From 0a9a17e3bb4564caf4bfe2a6783ae1287667d188 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 17 Nov 2017 11:05:43 -0600 Subject: ixgbe: Fix skb list corruption on Power systems This patch fixes an issue seen on Power systems with ixgbe which results in skb list corruption and an eventual kernel oops. The following is what was observed: CPU 1 CPU2 ============================ ============================ 1: ixgbe_xmit_frame_ring ixgbe_clean_tx_irq 2: first->skb = skb eop_desc = tx_buffer->next_to_watch 3: ixgbe_tx_map read_barrier_depends() 4: wmb check adapter written status bit 5: first->next_to_watch = tx_desc napi_consume_skb(tx_buffer->skb ..); 6: writel(i, tx_ring->tail); The read_barrier_depends is insufficient to ensure that tx_buffer->skb does not get loaded prior to tx_buffer->next_to_watch, which then results in loading a stale skb pointer. This patch replaces the read_barrier_depends with smp_rmb to ensure loads are ordered with respect to the load of tx_buffer->next_to_watch. Cc: stable Signed-off-by: Brian King Acked-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index ca06c3cc2ca8..62a18914f00f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1192,7 +1192,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, break; /* prevent any other reads prior to eop_desc */ - read_barrier_depends(); + smp_rmb(); /* if DD is not set pending work has not been completed */ if (!(eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD))) -- cgit v1.2.3-58-ga151 From 52c6912fde0133981ee50ba08808f257829c4c93 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 17 Nov 2017 11:05:44 -0600 Subject: i40e: Use smp_rmb rather than read_barrier_depends The original issue being fixed in this patch was seen with the ixgbe driver, but the same issue exists with i40e as well, as the code is very similar. read_barrier_depends is not sufficient to ensure loads following it are not speculatively loaded out of order by the CPU, which can result in stale data being loaded, causing potential system crashes. Cc: stable Signed-off-by: Brian King Acked-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 775d5a125887..4c08cc86463e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3966,7 +3966,7 @@ static bool i40e_clean_fdir_tx_irq(struct i40e_ring *tx_ring, int budget) break; /* prevent any other reads prior to eop_desc */ - read_barrier_depends(); + smp_rmb(); /* if the descriptor isn't done, no work yet to do */ if (!(eop_desc->cmd_type_offset_bsz & diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index d6d352a6e6ea..4566d66ffc7c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -759,7 +759,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi, break; /* prevent any other reads prior to eop_desc */ - read_barrier_depends(); + smp_rmb(); i40e_trace(clean_tx_irq, tx_ring, tx_desc, tx_buf); /* we have caught up to head, no work left to do */ -- cgit v1.2.3-58-ga151 From ae0c585d93dfaf923d2c7eb44b2c3ab92854ea9b Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 17 Nov 2017 11:05:45 -0600 Subject: ixgbevf: Use smp_rmb rather than read_barrier_depends The original issue being fixed in this patch was seen with the ixgbe driver, but the same issue exists with ixgbevf as well, as the code is very similar. read_barrier_depends is not sufficient to ensure loads following it are not speculatively loaded out of order by the CPU, which can result in stale data being loaded, causing potential system crashes. Cc: stable Signed-off-by: Brian King Acked-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index feed11bc9ddf..1f4a69134ade 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -326,7 +326,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, break; /* prevent any other reads prior to eop_desc */ - read_barrier_depends(); + smp_rmb(); /* if DD is not set pending work has not been completed */ if (!(eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD))) -- cgit v1.2.3-58-ga151 From 1e1f9ca546556e508d021545861f6b5fc75a95fe Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 17 Nov 2017 11:05:46 -0600 Subject: igbvf: Use smp_rmb rather than read_barrier_depends The original issue being fixed in this patch was seen with the ixgbe driver, but the same issue exists with igbvf as well, as the code is very similar. read_barrier_depends is not sufficient to ensure loads following it are not speculatively loaded out of order by the CPU, which can result in stale data being loaded, causing potential system crashes. Cc: stable Signed-off-by: Brian King Acked-by: Jesse Brandeburg Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igbvf/netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 713e8df23744..4214c1519a87 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -810,7 +810,7 @@ static bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring) break; /* prevent any other reads prior to eop_desc */ - read_barrier_depends(); + smp_rmb(); /* if DD is not set pending work has not been completed */ if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) -- cgit v1.2.3-58-ga151 From c4cb99185b4cc96c0a1c70104dc21ae14d7e7f28 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 17 Nov 2017 11:05:47 -0600 Subject: igb: Use smp_rmb rather than read_barrier_depends The original issue being fixed in this patch was seen with the ixgbe driver, but the same issue exists with igb as well, as the code is very similar. read_barrier_depends is not sufficient to ensure loads following it are not speculatively loaded out of order by the CPU, which can result in stale data being loaded, causing potential system crashes. Cc: stable Signed-off-by: Brian King Acked-by: Jesse Brandeburg Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index e94d3c256667..c208753ff5b7 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -7317,7 +7317,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget) break; /* prevent any other reads prior to eop_desc */ - read_barrier_depends(); + smp_rmb(); /* if DD is not set pending work has not been completed */ if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) -- cgit v1.2.3-58-ga151 From 7b8edcc685b5e2c3c37aa13dc50a88e84a5bfef8 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 17 Nov 2017 11:05:48 -0600 Subject: fm10k: Use smp_rmb rather than read_barrier_depends The original issue being fixed in this patch was seen with the ixgbe driver, but the same issue exists with fm10k as well, as the code is very similar. read_barrier_depends is not sufficient to ensure loads following it are not speculatively loaded out of order by the CPU, which can result in stale data being loaded, causing potential system crashes. Cc: stable Signed-off-by: Brian King Acked-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index dbd69310f263..538b42d5c187 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1231,7 +1231,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector, break; /* prevent any other reads prior to eop_desc */ - read_barrier_depends(); + smp_rmb(); /* if DD is not set pending work has not been completed */ if (!(eop_desc->flags & FM10K_TXD_FLAG_DONE)) -- cgit v1.2.3-58-ga151 From f72271e2a0ae4277d53c4053f5eed8bb346ba38a Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 17 Nov 2017 11:05:49 -0600 Subject: i40evf: Use smp_rmb rather than read_barrier_depends The original issue being fixed in this patch was seen with the ixgbe driver, but the same issue exists with i40evf as well, as the code is very similar. read_barrier_depends is not sufficient to ensure loads following it are not speculatively loaded out of order by the CPU, which can result in stale data being loaded, causing potential system crashes. Cc: stable Signed-off-by: Brian King Acked-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index fe817e2b6fef..50864f99446d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -179,7 +179,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi, break; /* prevent any other reads prior to eop_desc */ - read_barrier_depends(); + smp_rmb(); i40e_trace(clean_tx_irq, tx_ring, tx_desc, tx_buf); /* if the descriptor isn't done, no work yet to do */ -- cgit v1.2.3-58-ga151