Commit eba688b1 authored by Shannon Nelson's avatar Shannon Nelson Committed by David S. Miller

ionic: generic filter add

In preparation for adding vlan overflow management, rework
the ionic_lif_addr_add() function to something a little more
generic that can be used for other filter types.
Signed-off-by: default avatarShannon Nelson <snelson@pensando.io>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ff542fbe
...@@ -301,22 +301,19 @@ int ionic_lif_list_addr(struct ionic_lif *lif, const u8 *addr, bool mode) ...@@ -301,22 +301,19 @@ int ionic_lif_list_addr(struct ionic_lif *lif, const u8 *addr, bool mode)
return 0; return 0;
} }
int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr) static int ionic_lif_filter_add(struct ionic_lif *lif,
struct ionic_rx_filter_add_cmd *ac)
{ {
struct ionic_admin_ctx ctx = { struct ionic_admin_ctx ctx = {
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), .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_MAC),
},
}; };
int nfilters = le32_to_cpu(lif->identity->eth.max_ucast_filters);
bool mc = is_multicast_ether_addr(addr);
struct ionic_rx_filter *f; struct ionic_rx_filter *f;
int nfilters;
int err = 0; int err = 0;
memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, ETH_ALEN); ctx.cmd.rx_filter_add = *ac;
ctx.cmd.rx_filter_add.opcode = IONIC_CMD_RX_FILTER_ADD,
ctx.cmd.rx_filter_add.lif_index = cpu_to_le16(lif->index),
spin_lock_bh(&lif->rx_filters.lock); spin_lock_bh(&lif->rx_filters.lock);
f = ionic_rx_filter_find(lif, &ctx.cmd.rx_filter_add); f = ionic_rx_filter_find(lif, &ctx.cmd.rx_filter_add);
...@@ -338,22 +335,34 @@ int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr) ...@@ -338,22 +335,34 @@ int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr)
if (err) if (err)
return err; return err;
netdev_dbg(lif->netdev, "rx_filter add ADDR %pM\n", addr);
/* Don't bother with the write to FW if we know there's no room, /* Don't bother with the write to FW if we know there's no room,
* we can try again on the next sync attempt. * we can try again on the next sync attempt.
*/ */
switch (le16_to_cpu(ctx.cmd.rx_filter_add.match)) {
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);
nfilters = le32_to_cpu(lif->identity->eth.max_ucast_filters);
if ((lif->nucast + lif->nmcast) >= nfilters) if ((lif->nucast + lif->nmcast) >= nfilters)
err = -ENOSPC; err = -ENOSPC;
else break;
}
if (err != -ENOSPC)
err = ionic_adminq_post_wait(lif, &ctx); err = ionic_adminq_post_wait(lif, &ctx);
spin_lock_bh(&lif->rx_filters.lock); spin_lock_bh(&lif->rx_filters.lock);
if (err && err != -EEXIST) { if (err && err != -EEXIST) {
/* set the state back to NEW so we can try again later */ /* set the state back to NEW so we can try again later */
f = ionic_rx_filter_find(lif, &ctx.cmd.rx_filter_add); f = ionic_rx_filter_find(lif, &ctx.cmd.rx_filter_add);
if (f && f->state == IONIC_FILTER_STATE_SYNCED) { if (f && f->state == IONIC_FILTER_STATE_SYNCED) {
f->state = IONIC_FILTER_STATE_NEW; f->state = IONIC_FILTER_STATE_NEW;
/* If -ENOSPC we won't waste time trying to sync again
* until there is a delete that might make room
*/
if (err != -ENOSPC)
set_bit(IONIC_LIF_F_FILTER_SYNC_NEEDED, lif->state); set_bit(IONIC_LIF_F_FILTER_SYNC_NEEDED, lif->state);
} }
...@@ -361,14 +370,18 @@ int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr) ...@@ -361,14 +370,18 @@ int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr)
if (err == -ENOSPC) if (err == -ENOSPC)
return 0; return 0;
else
return err; return err;
} }
if (mc) switch (le16_to_cpu(ctx.cmd.rx_filter_add.match)) {
case IONIC_RX_FILTER_MATCH_MAC:
if (is_multicast_ether_addr(ctx.cmd.rx_filter_add.mac.addr))
lif->nmcast++; lif->nmcast++;
else else
lif->nucast++; lif->nucast++;
break;
}
f = ionic_rx_filter_find(lif, &ctx.cmd.rx_filter_add); f = ionic_rx_filter_find(lif, &ctx.cmd.rx_filter_add);
if (f && f->state == IONIC_FILTER_STATE_OLD) { if (f && f->state == IONIC_FILTER_STATE_OLD) {
...@@ -389,6 +402,17 @@ int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr) ...@@ -389,6 +402,17 @@ int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr)
return err; return err;
} }
int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr)
{
struct ionic_rx_filter_add_cmd ac = {
.match = cpu_to_le16(IONIC_RX_FILTER_MATCH_MAC),
};
memcpy(&ac.mac.addr, addr, ETH_ALEN);
return ionic_lif_filter_add(lif, &ac);
}
int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr) int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr)
{ {
struct ionic_admin_ctx ctx = { struct ionic_admin_ctx ctx = {
...@@ -493,7 +517,7 @@ void ionic_rx_filter_sync(struct ionic_lif *lif) ...@@ -493,7 +517,7 @@ void ionic_rx_filter_sync(struct ionic_lif *lif)
} }
list_for_each_entry_safe(sync_item, spos, &sync_add_list, list) { list_for_each_entry_safe(sync_item, spos, &sync_add_list, list) {
(void)ionic_lif_addr_add(lif, sync_item->f.cmd.mac.addr); (void)ionic_lif_filter_add(lif, &sync_item->f.cmd);
list_del(&sync_item->list); list_del(&sync_item->list);
devm_kfree(dev, sync_item); devm_kfree(dev, sync_item);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment