Skip to content

Commit 9b0b6ba

Browse files
emuslndavem330
authored andcommitted
ionic: handle vlan id overflow
Add vlans to the existing rx_filter_sync mechanics currently used for managing mac filters. Older versions of our firmware had no enforced limits on the number of vlans that the LIF could request, but requesting large numbers of vlans caused issues in FW memory management, so an arbitrary limit was added in the FW. The FW now returns -ENOSPC when it hits that limit, which the driver needs to handle. Unfortunately, the FW doesn't advertise the vlan id limit, as it does with mac filters, so the driver won't know the limit until it bumps into it. We'll grab the current vlan id count and use that as the limit from there on and thus prevent getting any more -ENOSPC errors. Just as is done for the mac filters, the device puts the device into promiscuous mode when -ENOSPC is seen for vlan ids, and the driver will track the vlans that aren't synced to the FW. When vlans are removed, the driver will retry the un-synced vlans. If all outstanding vlans are synced, the promiscuous mode will be disabled. Signed-off-by: Shannon Nelson <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c2b63d3 commit 9b0b6ba

File tree

4 files changed

+56
-41
lines changed

4 files changed

+56
-41
lines changed

drivers/net/ethernet/pensando/ionic/ionic_lif.c

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,7 @@ void ionic_lif_rx_mode(struct ionic_lif *lif)
12731273
rx_mode |= (nd_flags & IFF_PROMISC) ? IONIC_RX_MODE_F_PROMISC : 0;
12741274
rx_mode |= (nd_flags & IFF_ALLMULTI) ? IONIC_RX_MODE_F_ALLMULTI : 0;
12751275

1276-
/* sync the mac filters */
1276+
/* sync the filters */
12771277
ionic_rx_filter_sync(lif);
12781278

12791279
/* check for overflow state
@@ -1284,7 +1284,8 @@ void ionic_lif_rx_mode(struct ionic_lif *lif)
12841284
*/
12851285
nfilters = le32_to_cpu(lif->identity->eth.max_ucast_filters);
12861286

1287-
if ((lif->nucast + lif->nmcast) >= nfilters) {
1287+
if (((lif->nucast + lif->nmcast) >= nfilters) ||
1288+
(lif->max_vlans && lif->nvlans >= lif->max_vlans)) {
12881289
rx_mode |= IONIC_RX_MODE_F_PROMISC;
12891290
rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
12901291
} else {
@@ -1672,59 +1673,30 @@ static int ionic_vlan_rx_add_vid(struct net_device *netdev, __be16 proto,
16721673
u16 vid)
16731674
{
16741675
struct ionic_lif *lif = netdev_priv(netdev);
1675-
struct ionic_admin_ctx ctx = {
1676-
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
1677-
.cmd.rx_filter_add = {
1678-
.opcode = IONIC_CMD_RX_FILTER_ADD,
1679-
.lif_index = cpu_to_le16(lif->index),
1680-
.match = cpu_to_le16(IONIC_RX_FILTER_MATCH_VLAN),
1681-
.vlan.vlan = cpu_to_le16(vid),
1682-
},
1683-
};
16841676
int err;
16851677

1686-
netdev_dbg(netdev, "rx_filter add VLAN %d\n", vid);
1687-
err = ionic_adminq_post_wait(lif, &ctx);
1678+
err = ionic_lif_vlan_add(lif, vid);
16881679
if (err)
16891680
return err;
16901681

1691-
spin_lock_bh(&lif->rx_filters.lock);
1692-
err = ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx,
1693-
IONIC_FILTER_STATE_SYNCED);
1694-
spin_unlock_bh(&lif->rx_filters.lock);
1682+
ionic_lif_rx_mode(lif);
16951683

1696-
return err;
1684+
return 0;
16971685
}
16981686

16991687
static int ionic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto,
17001688
u16 vid)
17011689
{
17021690
struct ionic_lif *lif = netdev_priv(netdev);
1703-
struct ionic_admin_ctx ctx = {
1704-
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
1705-
.cmd.rx_filter_del = {
1706-
.opcode = IONIC_CMD_RX_FILTER_DEL,
1707-
.lif_index = cpu_to_le16(lif->index),
1708-
},
1709-
};
1710-
struct ionic_rx_filter *f;
1711-
1712-
spin_lock_bh(&lif->rx_filters.lock);
1713-
1714-
f = ionic_rx_filter_by_vlan(lif, vid);
1715-
if (!f) {
1716-
spin_unlock_bh(&lif->rx_filters.lock);
1717-
return -ENOENT;
1718-
}
1691+
int err;
17191692

1720-
netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n",
1721-
vid, f->filter_id);
1693+
err = ionic_lif_vlan_del(lif, vid);
1694+
if (err)
1695+
return err;
17221696

1723-
ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
1724-
ionic_rx_filter_free(lif, f);
1725-
spin_unlock_bh(&lif->rx_filters.lock);
1697+
ionic_lif_rx_mode(lif);
17261698

1727-
return ionic_adminq_post_wait(lif, &ctx);
1699+
return 0;
17281700
}
17291701

17301702
int ionic_lif_rss_config(struct ionic_lif *lif, const u16 types,

drivers/net/ethernet/pensando/ionic/ionic_lif.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ struct ionic_lif {
192192
u16 lif_type;
193193
unsigned int nmcast;
194194
unsigned int nucast;
195+
unsigned int nvlans;
196+
unsigned int max_vlans;
195197
char name[IONIC_LIF_NAME_MAX_SZ];
196198

197199
union ionic_lif_identity *identity;

drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,16 @@ static int ionic_lif_filter_add(struct ionic_lif *lif,
337337

338338
/* Don't bother with the write to FW if we know there's no room,
339339
* we can try again on the next sync attempt.
340+
* Since the FW doesn't have a way to tell us the vlan limit,
341+
* we start max_vlans at 0 until we hit the ENOSPC error.
340342
*/
341343
switch (le16_to_cpu(ctx.cmd.rx_filter_add.match)) {
344+
case IONIC_RX_FILTER_MATCH_VLAN:
345+
netdev_dbg(lif->netdev, "%s: rx_filter add VLAN %d\n",
346+
__func__, ctx.cmd.rx_filter_add.vlan.vlan);
347+
if (lif->max_vlans && lif->nvlans >= lif->max_vlans)
348+
err = -ENOSPC;
349+
break;
342350
case IONIC_RX_FILTER_MATCH_MAC:
343351
netdev_dbg(lif->netdev, "%s: rx_filter add ADDR %pM\n",
344352
__func__, ctx.cmd.rx_filter_add.mac.addr);
@@ -368,13 +376,19 @@ static int ionic_lif_filter_add(struct ionic_lif *lif,
368376

369377
spin_unlock_bh(&lif->rx_filters.lock);
370378

371-
if (err == -ENOSPC)
379+
if (err == -ENOSPC) {
380+
if (le16_to_cpu(ctx.cmd.rx_filter_add.match) == IONIC_RX_FILTER_MATCH_VLAN)
381+
lif->max_vlans = lif->nvlans;
372382
return 0;
383+
}
373384

374385
return err;
375386
}
376387

377388
switch (le16_to_cpu(ctx.cmd.rx_filter_add.match)) {
389+
case IONIC_RX_FILTER_MATCH_VLAN:
390+
lif->nvlans++;
391+
break;
378392
case IONIC_RX_FILTER_MATCH_MAC:
379393
if (is_multicast_ether_addr(ctx.cmd.rx_filter_add.mac.addr))
380394
lif->nmcast++;
@@ -413,6 +427,16 @@ int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr)
413427
return ionic_lif_filter_add(lif, &ac);
414428
}
415429

430+
int ionic_lif_vlan_add(struct ionic_lif *lif, const u16 vid)
431+
{
432+
struct ionic_rx_filter_add_cmd ac = {
433+
.match = cpu_to_le16(IONIC_RX_FILTER_MATCH_VLAN),
434+
.vlan.vlan = cpu_to_le16(vid),
435+
};
436+
437+
return ionic_lif_filter_add(lif, &ac);
438+
}
439+
416440
static int ionic_lif_filter_del(struct ionic_lif *lif,
417441
struct ionic_rx_filter_add_cmd *ac)
418442
{
@@ -435,6 +459,11 @@ static int ionic_lif_filter_del(struct ionic_lif *lif,
435459
}
436460

437461
switch (le16_to_cpu(ac->match)) {
462+
case IONIC_RX_FILTER_MATCH_VLAN:
463+
netdev_dbg(lif->netdev, "%s: rx_filter del VLAN %d id %d\n",
464+
__func__, ac->vlan.vlan, f->filter_id);
465+
lif->nvlans--;
466+
break;
438467
case IONIC_RX_FILTER_MATCH_MAC:
439468
netdev_dbg(lif->netdev, "%s: rx_filter del ADDR %pM id %d\n",
440469
__func__, ac->mac.addr, f->filter_id);
@@ -471,6 +500,16 @@ int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr)
471500
return ionic_lif_filter_del(lif, &ac);
472501
}
473502

503+
int ionic_lif_vlan_del(struct ionic_lif *lif, const u16 vid)
504+
{
505+
struct ionic_rx_filter_add_cmd ac = {
506+
.match = cpu_to_le16(IONIC_RX_FILTER_MATCH_VLAN),
507+
.vlan.vlan = cpu_to_le16(vid),
508+
};
509+
510+
return ionic_lif_filter_del(lif, &ac);
511+
}
512+
474513
struct sync_item {
475514
struct list_head list;
476515
struct ionic_rx_filter f;

drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,7 @@ struct ionic_rx_filter *ionic_rx_filter_rxsteer(struct ionic_lif *lif);
4444
void ionic_rx_filter_sync(struct ionic_lif *lif);
4545
int ionic_lif_list_addr(struct ionic_lif *lif, const u8 *addr, bool mode);
4646
int ionic_rx_filters_need_sync(struct ionic_lif *lif);
47+
int ionic_lif_vlan_add(struct ionic_lif *lif, const u16 vid);
48+
int ionic_lif_vlan_del(struct ionic_lif *lif, const u16 vid);
4749

4850
#endif /* _IONIC_RX_FILTER_H_ */

0 commit comments

Comments
 (0)