summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.c52
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.h2
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c41
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h2
4 files changed, 56 insertions, 41 deletions
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 4a080612142a..893a80e36632 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1273,7 +1273,7 @@ void ionic_lif_rx_mode(struct ionic_lif *lif)
rx_mode |= (nd_flags & IFF_PROMISC) ? IONIC_RX_MODE_F_PROMISC : 0;
rx_mode |= (nd_flags & IFF_ALLMULTI) ? IONIC_RX_MODE_F_ALLMULTI : 0;
- /* sync the mac filters */
+ /* sync the filters */
ionic_rx_filter_sync(lif);
/* check for overflow state
@@ -1284,7 +1284,8 @@ void ionic_lif_rx_mode(struct ionic_lif *lif)
*/
nfilters = le32_to_cpu(lif->identity->eth.max_ucast_filters);
- if ((lif->nucast + lif->nmcast) >= nfilters) {
+ if (((lif->nucast + lif->nmcast) >= nfilters) ||
+ (lif->max_vlans && lif->nvlans >= lif->max_vlans)) {
rx_mode |= IONIC_RX_MODE_F_PROMISC;
rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
} else {
@@ -1672,59 +1673,30 @@ static int ionic_vlan_rx_add_vid(struct net_device *netdev, __be16 proto,
u16 vid)
{
struct ionic_lif *lif = netdev_priv(netdev);
- struct ionic_admin_ctx ctx = {
- .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
- .cmd.rx_filter_add = {
- .opcode = IONIC_CMD_RX_FILTER_ADD,
- .lif_index = cpu_to_le16(lif->index),
- .match = cpu_to_le16(IONIC_RX_FILTER_MATCH_VLAN),
- .vlan.vlan = cpu_to_le16(vid),
- },
- };
int err;
- netdev_dbg(netdev, "rx_filter add VLAN %d\n", vid);
- err = ionic_adminq_post_wait(lif, &ctx);
+ err = ionic_lif_vlan_add(lif, vid);
if (err)
return err;
- spin_lock_bh(&lif->rx_filters.lock);
- err = ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx,
- IONIC_FILTER_STATE_SYNCED);
- spin_unlock_bh(&lif->rx_filters.lock);
+ ionic_lif_rx_mode(lif);
- return err;
+ return 0;
}
static int ionic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto,
u16 vid)
{
struct ionic_lif *lif = netdev_priv(netdev);
- struct ionic_admin_ctx ctx = {
- .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
- .cmd.rx_filter_del = {
- .opcode = IONIC_CMD_RX_FILTER_DEL,
- .lif_index = cpu_to_le16(lif->index),
- },
- };
- struct ionic_rx_filter *f;
-
- spin_lock_bh(&lif->rx_filters.lock);
-
- f = ionic_rx_filter_by_vlan(lif, vid);
- if (!f) {
- spin_unlock_bh(&lif->rx_filters.lock);
- return -ENOENT;
- }
+ int err;
- netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n",
- vid, f->filter_id);
+ err = ionic_lif_vlan_del(lif, vid);
+ if (err)
+ return err;
- ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
- ionic_rx_filter_free(lif, f);
- spin_unlock_bh(&lif->rx_filters.lock);
+ ionic_lif_rx_mode(lif);
- return ionic_adminq_post_wait(lif, &ctx);
+ return 0;
}
int ionic_lif_rss_config(struct ionic_lif *lif, const u16 types,
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
index 541aa54e4ffd..9f7ab2f17f93 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
@@ -192,6 +192,8 @@ struct ionic_lif {
u16 lif_type;
unsigned int nmcast;
unsigned int nucast;
+ unsigned int nvlans;
+ unsigned int max_vlans;
char name[IONIC_LIF_NAME_MAX_SZ];
union ionic_lif_identity *identity;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c
index 40a12b9df982..366f15794866 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c
@@ -337,8 +337,16 @@ static int ionic_lif_filter_add(struct ionic_lif *lif,
/* Don't bother with the write to FW if we know there's no room,
* we can try again on the next sync attempt.
+ * Since the FW doesn't have a way to tell us the vlan limit,
+ * we start max_vlans at 0 until we hit the ENOSPC error.
*/
switch (le16_to_cpu(ctx.cmd.rx_filter_add.match)) {
+ case IONIC_RX_FILTER_MATCH_VLAN:
+ netdev_dbg(lif->netdev, "%s: rx_filter add VLAN %d\n",
+ __func__, ctx.cmd.rx_filter_add.vlan.vlan);
+ if (lif->max_vlans && lif->nvlans >= lif->max_vlans)
+ err = -ENOSPC;
+ break;
case IONIC_RX_FILTER_MATCH_MAC:
netdev_dbg(lif->netdev, "%s: rx_filter add ADDR %pM\n",
__func__, ctx.cmd.rx_filter_add.mac.addr);
@@ -368,13 +376,19 @@ static int ionic_lif_filter_add(struct ionic_lif *lif,
spin_unlock_bh(&lif->rx_filters.lock);
- if (err == -ENOSPC)
+ if (err == -ENOSPC) {
+ if (le16_to_cpu(ctx.cmd.rx_filter_add.match) == IONIC_RX_FILTER_MATCH_VLAN)
+ lif->max_vlans = lif->nvlans;
return 0;
+ }
return err;
}
switch (le16_to_cpu(ctx.cmd.rx_filter_add.match)) {
+ case IONIC_RX_FILTER_MATCH_VLAN:
+ lif->nvlans++;
+ break;
case IONIC_RX_FILTER_MATCH_MAC:
if (is_multicast_ether_addr(ctx.cmd.rx_filter_add.mac.addr))
lif->nmcast++;
@@ -413,6 +427,16 @@ int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr)
return ionic_lif_filter_add(lif, &ac);
}
+int ionic_lif_vlan_add(struct ionic_lif *lif, const u16 vid)
+{
+ struct ionic_rx_filter_add_cmd ac = {
+ .match = cpu_to_le16(IONIC_RX_FILTER_MATCH_VLAN),
+ .vlan.vlan = cpu_to_le16(vid),
+ };
+
+ return ionic_lif_filter_add(lif, &ac);
+}
+
static int ionic_lif_filter_del(struct ionic_lif *lif,
struct ionic_rx_filter_add_cmd *ac)
{
@@ -435,6 +459,11 @@ static int ionic_lif_filter_del(struct ionic_lif *lif,
}
switch (le16_to_cpu(ac->match)) {
+ case IONIC_RX_FILTER_MATCH_VLAN:
+ netdev_dbg(lif->netdev, "%s: rx_filter del VLAN %d id %d\n",
+ __func__, ac->vlan.vlan, f->filter_id);
+ lif->nvlans--;
+ break;
case IONIC_RX_FILTER_MATCH_MAC:
netdev_dbg(lif->netdev, "%s: rx_filter del ADDR %pM id %d\n",
__func__, ac->mac.addr, f->filter_id);
@@ -471,6 +500,16 @@ int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr)
return ionic_lif_filter_del(lif, &ac);
}
+int ionic_lif_vlan_del(struct ionic_lif *lif, const u16 vid)
+{
+ struct ionic_rx_filter_add_cmd ac = {
+ .match = cpu_to_le16(IONIC_RX_FILTER_MATCH_VLAN),
+ .vlan.vlan = cpu_to_le16(vid),
+ };
+
+ return ionic_lif_filter_del(lif, &ac);
+}
+
struct sync_item {
struct list_head list;
struct ionic_rx_filter f;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h
index a66e35f0833b..87b2666f248b 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h
@@ -44,5 +44,7 @@ struct ionic_rx_filter *ionic_rx_filter_rxsteer(struct ionic_lif *lif);
void ionic_rx_filter_sync(struct ionic_lif *lif);
int ionic_lif_list_addr(struct ionic_lif *lif, const u8 *addr, bool mode);
int ionic_rx_filters_need_sync(struct ionic_lif *lif);
+int ionic_lif_vlan_add(struct ionic_lif *lif, const u16 vid);
+int ionic_lif_vlan_del(struct ionic_lif *lif, const u16 vid);
#endif /* _IONIC_RX_FILTER_H_ */