Skip to content

Commit 2d3d4ec

Browse files
jco-xilinxdavem330
authored andcommitted
sfc: fixes to filter restore handling
If the NIC is switched from full-featured to low-latency, encapsulated filters are no longer available, and this causes errors. This patch removes those filters from the filter table on restore. Also, if filters which are removed by the above, or which we fail to insert when restoring filters, were UC, MC or broadcast default filters, invalidate the corresponding vlan->default_filters entry. Signed-off-by: Edward Cree <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2b368b2 commit 2d3d4ec

File tree

1 file changed

+38
-4
lines changed
  • drivers/net/ethernet/sfc

1 file changed

+38
-4
lines changed

drivers/net/ethernet/sfc/ef10.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4557,9 +4557,12 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
45574557
{
45584558
struct efx_ef10_filter_table *table = efx->filter_state;
45594559
struct efx_ef10_nic_data *nic_data = efx->nic_data;
4560+
unsigned int invalid_filters = 0, failed = 0;
4561+
struct efx_ef10_filter_vlan *vlan;
45604562
struct efx_filter_spec *spec;
45614563
unsigned int filter_idx;
4562-
bool failed = false;
4564+
u32 mcdi_flags;
4565+
int match_pri;
45634566
int rc;
45644567

45654568
WARN_ON(!rwsem_is_locked(&efx->filter_sem));
@@ -4577,17 +4580,40 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
45774580
if (!spec)
45784581
continue;
45794582

4583+
mcdi_flags = efx_ef10_filter_mcdi_flags_from_spec(spec);
4584+
match_pri = 0;
4585+
while (match_pri < table->rx_match_count &&
4586+
table->rx_match_mcdi_flags[match_pri] != mcdi_flags)
4587+
++match_pri;
4588+
if (match_pri >= table->rx_match_count) {
4589+
invalid_filters++;
4590+
goto not_restored;
4591+
}
4592+
if (spec->rss_context != EFX_FILTER_RSS_CONTEXT_DEFAULT &&
4593+
spec->rss_context != nic_data->rx_rss_context)
4594+
netif_warn(efx, drv, efx->net_dev,
4595+
"Warning: unable to restore a filter with specific RSS context.\n");
4596+
45804597
table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_BUSY;
45814598
spin_unlock_bh(&efx->filter_lock);
45824599

45834600
rc = efx_ef10_filter_push(efx, spec,
45844601
&table->entry[filter_idx].handle,
45854602
false);
45864603
if (rc)
4587-
failed = true;
4588-
4604+
failed++;
45894605
spin_lock_bh(&efx->filter_lock);
4606+
45904607
if (rc) {
4608+
not_restored:
4609+
list_for_each_entry(vlan, &table->vlan_list, list) {
4610+
if (vlan->ucdef == filter_idx)
4611+
vlan->ucdef = EFX_EF10_FILTER_ID_INVALID;
4612+
if (vlan->mcdef == filter_idx)
4613+
vlan->mcdef = EFX_EF10_FILTER_ID_INVALID;
4614+
if (vlan->bcast == filter_idx)
4615+
vlan->bcast = EFX_EF10_FILTER_ID_INVALID;
4616+
}
45914617
kfree(spec);
45924618
efx_ef10_filter_set_entry(table, filter_idx, NULL, 0);
45934619
} else {
@@ -4598,9 +4624,17 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
45984624

45994625
spin_unlock_bh(&efx->filter_lock);
46004626

4627+
/* This can happen validly if the MC's capabilities have changed, so
4628+
* is not an error.
4629+
*/
4630+
if (invalid_filters)
4631+
netif_dbg(efx, drv, efx->net_dev,
4632+
"Did not restore %u filters that are now unsupported.\n",
4633+
invalid_filters);
4634+
46014635
if (failed)
46024636
netif_err(efx, hw, efx->net_dev,
4603-
"unable to restore all filters\n");
4637+
"unable to restore %u filters\n", failed);
46044638
else
46054639
nic_data->must_restore_filters = false;
46064640
}

0 commit comments

Comments
 (0)