|
@@ -4557,9 +4557,12 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
|
|
{
|
|
{
|
|
struct efx_ef10_filter_table *table = efx->filter_state;
|
|
struct efx_ef10_filter_table *table = efx->filter_state;
|
|
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
|
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
|
|
|
+ unsigned int invalid_filters = 0, failed = 0;
|
|
|
|
+ struct efx_ef10_filter_vlan *vlan;
|
|
struct efx_filter_spec *spec;
|
|
struct efx_filter_spec *spec;
|
|
unsigned int filter_idx;
|
|
unsigned int filter_idx;
|
|
- bool failed = false;
|
|
|
|
|
|
+ u32 mcdi_flags;
|
|
|
|
+ int match_pri;
|
|
int rc;
|
|
int rc;
|
|
|
|
|
|
WARN_ON(!rwsem_is_locked(&efx->filter_sem));
|
|
WARN_ON(!rwsem_is_locked(&efx->filter_sem));
|
|
@@ -4577,6 +4580,20 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
|
|
if (!spec)
|
|
if (!spec)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
+ mcdi_flags = efx_ef10_filter_mcdi_flags_from_spec(spec);
|
|
|
|
+ match_pri = 0;
|
|
|
|
+ while (match_pri < table->rx_match_count &&
|
|
|
|
+ table->rx_match_mcdi_flags[match_pri] != mcdi_flags)
|
|
|
|
+ ++match_pri;
|
|
|
|
+ if (match_pri >= table->rx_match_count) {
|
|
|
|
+ invalid_filters++;
|
|
|
|
+ goto not_restored;
|
|
|
|
+ }
|
|
|
|
+ if (spec->rss_context != EFX_FILTER_RSS_CONTEXT_DEFAULT &&
|
|
|
|
+ spec->rss_context != nic_data->rx_rss_context)
|
|
|
|
+ netif_warn(efx, drv, efx->net_dev,
|
|
|
|
+ "Warning: unable to restore a filter with specific RSS context.\n");
|
|
|
|
+
|
|
table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_BUSY;
|
|
table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_BUSY;
|
|
spin_unlock_bh(&efx->filter_lock);
|
|
spin_unlock_bh(&efx->filter_lock);
|
|
|
|
|
|
@@ -4584,10 +4601,19 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
|
|
&table->entry[filter_idx].handle,
|
|
&table->entry[filter_idx].handle,
|
|
false);
|
|
false);
|
|
if (rc)
|
|
if (rc)
|
|
- failed = true;
|
|
|
|
-
|
|
|
|
|
|
+ failed++;
|
|
spin_lock_bh(&efx->filter_lock);
|
|
spin_lock_bh(&efx->filter_lock);
|
|
|
|
+
|
|
if (rc) {
|
|
if (rc) {
|
|
|
|
+not_restored:
|
|
|
|
+ list_for_each_entry(vlan, &table->vlan_list, list) {
|
|
|
|
+ if (vlan->ucdef == filter_idx)
|
|
|
|
+ vlan->ucdef = EFX_EF10_FILTER_ID_INVALID;
|
|
|
|
+ if (vlan->mcdef == filter_idx)
|
|
|
|
+ vlan->mcdef = EFX_EF10_FILTER_ID_INVALID;
|
|
|
|
+ if (vlan->bcast == filter_idx)
|
|
|
|
+ vlan->bcast = EFX_EF10_FILTER_ID_INVALID;
|
|
|
|
+ }
|
|
kfree(spec);
|
|
kfree(spec);
|
|
efx_ef10_filter_set_entry(table, filter_idx, NULL, 0);
|
|
efx_ef10_filter_set_entry(table, filter_idx, NULL, 0);
|
|
} else {
|
|
} else {
|
|
@@ -4598,9 +4624,17 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
|
|
|
|
|
|
spin_unlock_bh(&efx->filter_lock);
|
|
spin_unlock_bh(&efx->filter_lock);
|
|
|
|
|
|
|
|
+ /* This can happen validly if the MC's capabilities have changed, so
|
|
|
|
+ * is not an error.
|
|
|
|
+ */
|
|
|
|
+ if (invalid_filters)
|
|
|
|
+ netif_dbg(efx, drv, efx->net_dev,
|
|
|
|
+ "Did not restore %u filters that are now unsupported.\n",
|
|
|
|
+ invalid_filters);
|
|
|
|
+
|
|
if (failed)
|
|
if (failed)
|
|
netif_err(efx, hw, efx->net_dev,
|
|
netif_err(efx, hw, efx->net_dev,
|
|
- "unable to restore all filters\n");
|
|
|
|
|
|
+ "unable to restore %u filters\n", failed);
|
|
else
|
|
else
|
|
nic_data->must_restore_filters = false;
|
|
nic_data->must_restore_filters = false;
|
|
}
|
|
}
|