|
@@ -1870,12 +1870,10 @@ void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name,
|
|
aq_ret = i40e_aq_add_macvlan(hw, vsi->seid, list, num_add, NULL);
|
|
aq_ret = i40e_aq_add_macvlan(hw, vsi->seid, list, num_add, NULL);
|
|
aq_err = hw->aq.asq_last_status;
|
|
aq_err = hw->aq.asq_last_status;
|
|
fcnt = i40e_update_filter_state(num_add, list, add_head, aq_ret);
|
|
fcnt = i40e_update_filter_state(num_add, list, add_head, aq_ret);
|
|
- vsi->active_filters += fcnt;
|
|
|
|
|
|
|
|
if (fcnt != num_add) {
|
|
if (fcnt != num_add) {
|
|
*promisc_changed = true;
|
|
*promisc_changed = true;
|
|
set_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
|
|
set_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
|
|
- vsi->promisc_threshold = (vsi->active_filters * 3) / 4;
|
|
|
|
dev_warn(&vsi->back->pdev->dev,
|
|
dev_warn(&vsi->back->pdev->dev,
|
|
"Error %s adding RX filters on %s, promiscuous mode forced on\n",
|
|
"Error %s adding RX filters on %s, promiscuous mode forced on\n",
|
|
i40e_aq_str(hw, aq_err),
|
|
i40e_aq_str(hw, aq_err),
|
|
@@ -1939,6 +1937,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
struct i40e_hw *hw = &vsi->back->hw;
|
|
struct i40e_hw *hw = &vsi->back->hw;
|
|
unsigned int vlan_any_filters = 0;
|
|
unsigned int vlan_any_filters = 0;
|
|
unsigned int non_vlan_filters = 0;
|
|
unsigned int non_vlan_filters = 0;
|
|
|
|
+ unsigned int failed_filters = 0;
|
|
unsigned int vlan_filters = 0;
|
|
unsigned int vlan_filters = 0;
|
|
bool promisc_changed = false;
|
|
bool promisc_changed = false;
|
|
char vsi_name[16] = "PF";
|
|
char vsi_name[16] = "PF";
|
|
@@ -1985,7 +1984,6 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
/* Move the element into temporary del_list */
|
|
/* Move the element into temporary del_list */
|
|
hash_del(&f->hlist);
|
|
hash_del(&f->hlist);
|
|
hlist_add_head(&f->hlist, &tmp_del_list);
|
|
hlist_add_head(&f->hlist, &tmp_del_list);
|
|
- vsi->active_filters--;
|
|
|
|
|
|
|
|
/* Avoid counting removed filters */
|
|
/* Avoid counting removed filters */
|
|
continue;
|
|
continue;
|
|
@@ -2046,7 +2044,6 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
f->state = I40E_FILTER_REMOVE;
|
|
f->state = I40E_FILTER_REMOVE;
|
|
hash_del(&f->hlist);
|
|
hash_del(&f->hlist);
|
|
hlist_add_head(&f->hlist, &tmp_del_list);
|
|
hlist_add_head(&f->hlist, &tmp_del_list);
|
|
- vsi->active_filters--;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* Also update any filters on the tmp_add list */
|
|
/* Also update any filters on the tmp_add list */
|
|
@@ -2203,27 +2200,36 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
|
|
add_list = NULL;
|
|
add_list = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
- /* Check to see if we can drop out of overflow promiscuous mode. */
|
|
|
|
|
|
+ /* Determine the number of active and failed filters. */
|
|
|
|
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
|
|
|
|
+ vsi->active_filters = 0;
|
|
|
|
+ hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
|
|
|
|
+ if (f->state == I40E_FILTER_ACTIVE)
|
|
|
|
+ vsi->active_filters++;
|
|
|
|
+ else if (f->state == I40E_FILTER_FAILED)
|
|
|
|
+ failed_filters++;
|
|
|
|
+ }
|
|
|
|
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
|
|
|
|
+
|
|
|
|
+ /* If promiscuous mode has changed, we need to calculate a new
|
|
|
|
+ * threshold for when we are safe to exit
|
|
|
|
+ */
|
|
|
|
+ if (promisc_changed)
|
|
|
|
+ vsi->promisc_threshold = (vsi->active_filters * 3) / 4;
|
|
|
|
+
|
|
|
|
+ /* Check if we are able to exit overflow promiscuous mode. We can
|
|
|
|
+ * safely exit if we didn't just enter, we no longer have any failed
|
|
|
|
+ * filters, and we have reduced filters below the threshold value.
|
|
|
|
+ */
|
|
if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) &&
|
|
if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) &&
|
|
|
|
+ !promisc_changed && !failed_filters &&
|
|
(vsi->active_filters < vsi->promisc_threshold)) {
|
|
(vsi->active_filters < vsi->promisc_threshold)) {
|
|
- int failed_count = 0;
|
|
|
|
- /* See if we have any failed filters. We can't drop out of
|
|
|
|
- * promiscuous until these have all been deleted.
|
|
|
|
- */
|
|
|
|
- spin_lock_bh(&vsi->mac_filter_hash_lock);
|
|
|
|
- hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
|
|
|
|
- if (f->state == I40E_FILTER_FAILED)
|
|
|
|
- failed_count++;
|
|
|
|
- }
|
|
|
|
- spin_unlock_bh(&vsi->mac_filter_hash_lock);
|
|
|
|
- if (!failed_count) {
|
|
|
|
- dev_info(&pf->pdev->dev,
|
|
|
|
- "filter logjam cleared on %s, leaving overflow promiscuous mode\n",
|
|
|
|
- vsi_name);
|
|
|
|
- clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
|
|
|
|
- promisc_changed = true;
|
|
|
|
- vsi->promisc_threshold = 0;
|
|
|
|
- }
|
|
|
|
|
|
+ dev_info(&pf->pdev->dev,
|
|
|
|
+ "filter logjam cleared on %s, leaving overflow promiscuous mode\n",
|
|
|
|
+ vsi_name);
|
|
|
|
+ clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
|
|
|
|
+ promisc_changed = true;
|
|
|
|
+ vsi->promisc_threshold = 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* if the VF is not trusted do not do promisc */
|
|
/* if the VF is not trusted do not do promisc */
|