|
@@ -40,8 +40,8 @@ static const char i40e_driver_string[] =
|
|
|
#define DRV_KERN "-k"
|
|
|
|
|
|
#define DRV_VERSION_MAJOR 1
|
|
|
-#define DRV_VERSION_MINOR 5
|
|
|
-#define DRV_VERSION_BUILD 16
|
|
|
+#define DRV_VERSION_MINOR 6
|
|
|
+#define DRV_VERSION_BUILD 4
|
|
|
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
|
|
|
__stringify(DRV_VERSION_MINOR) "." \
|
|
|
__stringify(DRV_VERSION_BUILD) DRV_KERN
|
|
@@ -1579,14 +1579,8 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
|
|
|
vsi->tc_config.numtc = numtc;
|
|
|
vsi->tc_config.enabled_tc = enabled_tc ? enabled_tc : 1;
|
|
|
/* Number of queues per enabled TC */
|
|
|
- /* In MFP case we can have a much lower count of MSIx
|
|
|
- * vectors available and so we need to lower the used
|
|
|
- * q count.
|
|
|
- */
|
|
|
- if (pf->flags & I40E_FLAG_MSIX_ENABLED)
|
|
|
- qcount = min_t(int, vsi->alloc_queue_pairs, pf->num_lan_msix);
|
|
|
- else
|
|
|
- qcount = vsi->alloc_queue_pairs;
|
|
|
+ qcount = vsi->alloc_queue_pairs;
|
|
|
+
|
|
|
num_tc_qps = qcount / numtc;
|
|
|
num_tc_qps = min_t(int, num_tc_qps, i40e_pf_get_max_q_per_tc(pf));
|
|
|
|
|
@@ -1840,8 +1834,10 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
{
|
|
|
struct list_head tmp_del_list, tmp_add_list;
|
|
|
struct i40e_mac_filter *f, *ftmp, *fclone;
|
|
|
+ struct i40e_hw *hw = &vsi->back->hw;
|
|
|
bool promisc_forced_on = false;
|
|
|
bool add_happened = false;
|
|
|
+ char vsi_name[16] = "PF";
|
|
|
int filter_list_len = 0;
|
|
|
u32 changed_flags = 0;
|
|
|
i40e_status aq_ret = 0;
|
|
@@ -1869,6 +1865,11 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
INIT_LIST_HEAD(&tmp_del_list);
|
|
|
INIT_LIST_HEAD(&tmp_add_list);
|
|
|
|
|
|
+ if (vsi->type == I40E_VSI_SRIOV)
|
|
|
+ snprintf(vsi_name, sizeof(vsi_name) - 1, "VF %d", vsi->vf_id);
|
|
|
+ else if (vsi->type != I40E_VSI_MAIN)
|
|
|
+ snprintf(vsi_name, sizeof(vsi_name) - 1, "vsi %d", vsi->seid);
|
|
|
+
|
|
|
if (vsi->flags & I40E_VSI_FLAG_FILTER_CHANGED) {
|
|
|
vsi->flags &= ~I40E_VSI_FLAG_FILTER_CHANGED;
|
|
|
|
|
@@ -1920,7 +1921,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
if (!list_empty(&tmp_del_list)) {
|
|
|
int del_list_size;
|
|
|
|
|
|
- filter_list_len = pf->hw.aq.asq_buf_size /
|
|
|
+ filter_list_len = hw->aq.asq_buf_size /
|
|
|
sizeof(struct i40e_aqc_remove_macvlan_element_data);
|
|
|
del_list_size = filter_list_len *
|
|
|
sizeof(struct i40e_aqc_remove_macvlan_element_data);
|
|
@@ -1952,21 +1953,21 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
|
|
|
/* flush a full buffer */
|
|
|
if (num_del == filter_list_len) {
|
|
|
- aq_ret = i40e_aq_remove_macvlan(&pf->hw,
|
|
|
- vsi->seid,
|
|
|
- del_list,
|
|
|
- num_del,
|
|
|
- NULL);
|
|
|
- aq_err = pf->hw.aq.asq_last_status;
|
|
|
+ aq_ret =
|
|
|
+ i40e_aq_remove_macvlan(hw, vsi->seid,
|
|
|
+ del_list,
|
|
|
+ num_del, NULL);
|
|
|
+ aq_err = hw->aq.asq_last_status;
|
|
|
num_del = 0;
|
|
|
memset(del_list, 0, del_list_size);
|
|
|
|
|
|
if (aq_ret && aq_err != I40E_AQ_RC_ENOENT) {
|
|
|
retval = -EIO;
|
|
|
dev_err(&pf->pdev->dev,
|
|
|
- "ignoring delete macvlan error, err %s, aq_err %s while flushing a full buffer\n",
|
|
|
- i40e_stat_str(&pf->hw, aq_ret),
|
|
|
- i40e_aq_str(&pf->hw, aq_err));
|
|
|
+ "ignoring delete macvlan error on %s, err %s, aq_err %s while flushing a full buffer\n",
|
|
|
+ vsi_name,
|
|
|
+ i40e_stat_str(hw, aq_ret),
|
|
|
+ i40e_aq_str(hw, aq_err));
|
|
|
}
|
|
|
}
|
|
|
/* Release memory for MAC filter entries which were
|
|
@@ -1977,17 +1978,17 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
}
|
|
|
|
|
|
if (num_del) {
|
|
|
- aq_ret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid,
|
|
|
- del_list, num_del,
|
|
|
- NULL);
|
|
|
- aq_err = pf->hw.aq.asq_last_status;
|
|
|
+ aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, del_list,
|
|
|
+ num_del, NULL);
|
|
|
+ aq_err = hw->aq.asq_last_status;
|
|
|
num_del = 0;
|
|
|
|
|
|
if (aq_ret && aq_err != I40E_AQ_RC_ENOENT)
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
- "ignoring delete macvlan error, err %s aq_err %s\n",
|
|
|
- i40e_stat_str(&pf->hw, aq_ret),
|
|
|
- i40e_aq_str(&pf->hw, aq_err));
|
|
|
+ "ignoring delete macvlan error on %s, err %s aq_err %s\n",
|
|
|
+ vsi_name,
|
|
|
+ i40e_stat_str(hw, aq_ret),
|
|
|
+ i40e_aq_str(hw, aq_err));
|
|
|
}
|
|
|
|
|
|
kfree(del_list);
|
|
@@ -1998,7 +1999,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
int add_list_size;
|
|
|
|
|
|
/* do all the adds now */
|
|
|
- filter_list_len = pf->hw.aq.asq_buf_size /
|
|
|
+ filter_list_len = hw->aq.asq_buf_size /
|
|
|
sizeof(struct i40e_aqc_add_macvlan_element_data),
|
|
|
add_list_size = filter_list_len *
|
|
|
sizeof(struct i40e_aqc_add_macvlan_element_data);
|
|
@@ -2033,10 +2034,10 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
|
|
|
/* flush a full buffer */
|
|
|
if (num_add == filter_list_len) {
|
|
|
- aq_ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid,
|
|
|
+ aq_ret = i40e_aq_add_macvlan(hw, vsi->seid,
|
|
|
add_list, num_add,
|
|
|
NULL);
|
|
|
- aq_err = pf->hw.aq.asq_last_status;
|
|
|
+ aq_err = hw->aq.asq_last_status;
|
|
|
num_add = 0;
|
|
|
|
|
|
if (aq_ret)
|
|
@@ -2051,9 +2052,9 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
}
|
|
|
|
|
|
if (num_add) {
|
|
|
- aq_ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid,
|
|
|
+ aq_ret = i40e_aq_add_macvlan(hw, vsi->seid,
|
|
|
add_list, num_add, NULL);
|
|
|
- aq_err = pf->hw.aq.asq_last_status;
|
|
|
+ aq_err = hw->aq.asq_last_status;
|
|
|
num_add = 0;
|
|
|
}
|
|
|
kfree(add_list);
|
|
@@ -2062,16 +2063,18 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
if (add_happened && aq_ret && aq_err != I40E_AQ_RC_EINVAL) {
|
|
|
retval = i40e_aq_rc_to_posix(aq_ret, aq_err);
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
- "add filter failed, err %s aq_err %s\n",
|
|
|
- i40e_stat_str(&pf->hw, aq_ret),
|
|
|
- i40e_aq_str(&pf->hw, aq_err));
|
|
|
- if ((pf->hw.aq.asq_last_status == I40E_AQ_RC_ENOSPC) &&
|
|
|
+ "add filter failed on %s, err %s aq_err %s\n",
|
|
|
+ vsi_name,
|
|
|
+ i40e_stat_str(hw, aq_ret),
|
|
|
+ i40e_aq_str(hw, aq_err));
|
|
|
+ if ((hw->aq.asq_last_status == I40E_AQ_RC_ENOSPC) &&
|
|
|
!test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
|
|
|
&vsi->state)) {
|
|
|
promisc_forced_on = true;
|
|
|
set_bit(__I40E_FILTER_OVERFLOW_PROMISC,
|
|
|
&vsi->state);
|
|
|
- dev_info(&pf->pdev->dev, "promiscuous mode forced on\n");
|
|
|
+ dev_info(&pf->pdev->dev, "promiscuous mode forced on %s\n",
|
|
|
+ vsi_name);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -2093,12 +2096,12 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
NULL);
|
|
|
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 multi promisc failed, err %s aq_err %s\n",
|
|
|
- i40e_stat_str(&pf->hw, aq_ret),
|
|
|
- i40e_aq_str(&pf->hw,
|
|
|
- pf->hw.aq.asq_last_status));
|
|
|
+ "set multi 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));
|
|
|
}
|
|
|
}
|
|
|
if ((changed_flags & IFF_PROMISC) || promisc_forced_on) {
|
|
@@ -2117,33 +2120,58 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
*/
|
|
|
if (pf->cur_promisc != cur_promisc) {
|
|
|
pf->cur_promisc = cur_promisc;
|
|
|
- set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
|
|
|
+ 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(
|
|
|
- &vsi->back->hw,
|
|
|
+ hw,
|
|
|
vsi->seid,
|
|
|
cur_promisc, NULL,
|
|
|
true);
|
|
|
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 unicast promisc failed, err %d, aq_err %d\n",
|
|
|
- aq_ret, pf->hw.aq.asq_last_status);
|
|
|
+ "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(
|
|
|
- &vsi->back->hw,
|
|
|
+ hw,
|
|
|
vsi->seid,
|
|
|
cur_promisc, NULL);
|
|
|
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 multicast promisc failed, err %d, aq_err %d\n",
|
|
|
- aq_ret, pf->hw.aq.asq_last_status);
|
|
|
+ "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,
|
|
@@ -2154,9 +2182,9 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
|
pf->hw.aq.asq_last_status);
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
"set brdcast promisc failed, err %s, aq_err %s\n",
|
|
|
- i40e_stat_str(&pf->hw, aq_ret),
|
|
|
- i40e_aq_str(&pf->hw,
|
|
|
- pf->hw.aq.asq_last_status));
|
|
|
+ i40e_stat_str(hw, aq_ret),
|
|
|
+ i40e_aq_str(hw,
|
|
|
+ hw->aq.asq_last_status));
|
|
|
}
|
|
|
}
|
|
|
out:
|
|
@@ -3947,6 +3975,7 @@ static void i40e_vsi_free_irq(struct i40e_vsi *vsi)
|
|
|
/* clear the affinity_mask in the IRQ descriptor */
|
|
|
irq_set_affinity_hint(pf->msix_entries[vector].vector,
|
|
|
NULL);
|
|
|
+ synchronize_irq(pf->msix_entries[vector].vector);
|
|
|
free_irq(pf->msix_entries[vector].vector,
|
|
|
vsi->q_vectors[i]);
|
|
|
|
|
@@ -4953,7 +4982,6 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf)
|
|
|
if (pf->vsi[v]->netdev)
|
|
|
i40e_dcbnl_set_all(pf->vsi[v]);
|
|
|
}
|
|
|
- i40e_notify_client_of_l2_param_changes(pf->vsi[v]);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -5178,12 +5206,6 @@ static void i40e_vsi_reinit_locked(struct i40e_vsi *vsi)
|
|
|
usleep_range(1000, 2000);
|
|
|
i40e_down(vsi);
|
|
|
|
|
|
- /* Give a VF some time to respond to the reset. The
|
|
|
- * two second wait is based upon the watchdog cycle in
|
|
|
- * the VF driver.
|
|
|
- */
|
|
|
- if (vsi->type == I40E_VSI_SRIOV)
|
|
|
- msleep(2000);
|
|
|
i40e_up(vsi);
|
|
|
clear_bit(__I40E_CONFIG_BUSY, &pf->state);
|
|
|
}
|
|
@@ -5226,6 +5248,9 @@ void i40e_down(struct i40e_vsi *vsi)
|
|
|
i40e_clean_tx_ring(vsi->tx_rings[i]);
|
|
|
i40e_clean_rx_ring(vsi->rx_rings[i]);
|
|
|
}
|
|
|
+
|
|
|
+ i40e_notify_client_of_netdev_close(vsi, false);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -5704,6 +5729,8 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,
|
|
|
i40e_service_event_schedule(pf);
|
|
|
} else {
|
|
|
i40e_pf_unquiesce_all_vsi(pf);
|
|
|
+ /* Notify the client for the DCB changes */
|
|
|
+ i40e_notify_client_of_l2_param_changes(pf->vsi[pf->lan_vsi]);
|
|
|
}
|
|
|
|
|
|
exit:
|
|
@@ -5928,7 +5955,6 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
|
|
|
if (I40E_DEBUG_FD & pf->hw.debug_mask)
|
|
|
dev_info(&pf->pdev->dev, "FD Filter table flushed and FD-SB replayed.\n");
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -7160,7 +7186,7 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi)
|
|
|
vsi->alloc_queue_pairs = 1;
|
|
|
vsi->num_desc = ALIGN(I40E_FDIR_RING_COUNT,
|
|
|
I40E_REQ_DESCRIPTOR_MULTIPLE);
|
|
|
- vsi->num_q_vectors = 1;
|
|
|
+ vsi->num_q_vectors = pf->num_fdsb_msix;
|
|
|
break;
|
|
|
|
|
|
case I40E_VSI_VMDQ2:
|
|
@@ -7544,9 +7570,11 @@ static int i40e_init_msix(struct i40e_pf *pf)
|
|
|
/* reserve one vector for sideband flow director */
|
|
|
if (pf->flags & I40E_FLAG_FD_SB_ENABLED) {
|
|
|
if (vectors_left) {
|
|
|
+ pf->num_fdsb_msix = 1;
|
|
|
v_budget++;
|
|
|
vectors_left--;
|
|
|
} else {
|
|
|
+ pf->num_fdsb_msix = 0;
|
|
|
pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
|
|
|
}
|
|
|
}
|
|
@@ -8565,7 +8593,9 @@ bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features)
|
|
|
/* Enable filters and mark for reset */
|
|
|
if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
|
|
|
need_reset = true;
|
|
|
- pf->flags |= I40E_FLAG_FD_SB_ENABLED;
|
|
|
+ /* enable FD_SB only if there is MSI-X vector */
|
|
|
+ if (pf->num_fdsb_msix > 0)
|
|
|
+ pf->flags |= I40E_FLAG_FD_SB_ENABLED;
|
|
|
} else {
|
|
|
/* turn off filters, mark for reset and clear SW filter list */
|
|
|
if (pf->flags & I40E_FLAG_FD_SB_ENABLED) {
|
|
@@ -10053,14 +10083,14 @@ void i40e_veb_release(struct i40e_veb *veb)
|
|
|
static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi)
|
|
|
{
|
|
|
struct i40e_pf *pf = veb->pf;
|
|
|
- bool is_default = veb->pf->cur_promisc;
|
|
|
bool enable_stats = !!(pf->flags & I40E_FLAG_VEB_STATS_ENABLED);
|
|
|
int ret;
|
|
|
|
|
|
- /* get a VEB from the hardware */
|
|
|
ret = i40e_aq_add_veb(&pf->hw, veb->uplink_seid, vsi->seid,
|
|
|
- veb->enabled_tc, is_default,
|
|
|
+ veb->enabled_tc, false,
|
|
|
&veb->seid, enable_stats, NULL);
|
|
|
+
|
|
|
+ /* get a VEB from the hardware */
|
|
|
if (ret) {
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
"couldn't add VEB, err %s aq_err %s\n",
|
|
@@ -11441,6 +11471,7 @@ static int i40e_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
|
{
|
|
|
struct i40e_pf *pf = pci_get_drvdata(pdev);
|
|
|
struct i40e_hw *hw = &pf->hw;
|
|
|
+ int retval = 0;
|
|
|
|
|
|
set_bit(__I40E_SUSPENDED, &pf->state);
|
|
|
set_bit(__I40E_DOWN, &pf->state);
|
|
@@ -11452,10 +11483,16 @@ static int i40e_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
|
wr32(hw, I40E_PFPM_APM, (pf->wol_en ? I40E_PFPM_APM_APME_MASK : 0));
|
|
|
wr32(hw, I40E_PFPM_WUFC, (pf->wol_en ? I40E_PFPM_WUFC_MAG_MASK : 0));
|
|
|
|
|
|
+ i40e_stop_misc_vector(pf);
|
|
|
+
|
|
|
+ retval = pci_save_state(pdev);
|
|
|
+ if (retval)
|
|
|
+ return retval;
|
|
|
+
|
|
|
pci_wake_from_d3(pdev, pf->wol_en);
|
|
|
pci_set_power_state(pdev, PCI_D3hot);
|
|
|
|
|
|
- return 0;
|
|
|
+ return retval;
|
|
|
}
|
|
|
|
|
|
/**
|