aq_ret = i40e_aq_add_macvlan(hw, vsi->seid, list, num_add, NULL);
aq_err = hw->aq.asq_last_status;
fcnt = i40e_update_filter_state(num_add, list, add_head, aq_ret);
- vsi->active_filters += fcnt;
if (fcnt != num_add) {
*promisc_changed = true;
set_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
- vsi->promisc_threshold = (vsi->active_filters * 3) / 4;
dev_warn(&vsi->back->pdev->dev,
"Error %s adding RX filters on %s, promiscuous mode forced on\n",
i40e_aq_str(hw, aq_err),
struct i40e_hw *hw = &vsi->back->hw;
unsigned int vlan_any_filters = 0;
unsigned int non_vlan_filters = 0;
+ unsigned int failed_filters = 0;
unsigned int vlan_filters = 0;
bool promisc_changed = false;
char vsi_name[16] = "PF";
/* Move the element into temporary del_list */
hash_del(&f->hlist);
hlist_add_head(&f->hlist, &tmp_del_list);
- vsi->active_filters--;
/* Avoid counting removed filters */
continue;
f->state = I40E_FILTER_REMOVE;
hash_del(&f->hlist);
hlist_add_head(&f->hlist, &tmp_del_list);
- vsi->active_filters--;
}
/* Also update any filters on the tmp_add list */
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) &&
+ !promisc_changed && !failed_filters &&
(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 */