1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
4 #include <linux/netdevice.h>
5 #include <linux/dynamic_debug.h>
6 #include <linux/etherdevice.h>
10 #include "ionic_rx_filter.h"
12 void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f)
14 struct device *dev = lif->ionic->dev;
17 hlist_del(&f->by_hash);
21 void ionic_rx_filter_replay(struct ionic_lif *lif)
23 struct ionic_rx_filter_add_cmd *ac;
24 struct ionic_admin_ctx ctx;
25 struct ionic_rx_filter *f;
26 struct hlist_head *head;
27 struct hlist_node *tmp;
31 ac = &ctx.cmd.rx_filter_add;
33 for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
34 head = &lif->rx_filters.by_id[i];
35 hlist_for_each_entry_safe(f, tmp, head, by_id) {
36 ctx.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work);
37 memcpy(ac, &f->cmd, sizeof(f->cmd));
38 dev_dbg(&lif->netdev->dev, "replay filter command:\n");
39 dynamic_hex_dump("cmd ", DUMP_PREFIX_OFFSET, 16, 1,
40 &ctx.cmd, sizeof(ctx.cmd), true);
42 err = ionic_adminq_post_wait(lif, &ctx);
44 switch (le16_to_cpu(ac->match)) {
45 case IONIC_RX_FILTER_MATCH_VLAN:
46 netdev_info(lif->netdev, "Replay failed - %d: vlan %d\n",
48 le16_to_cpu(ac->vlan.vlan));
50 case IONIC_RX_FILTER_MATCH_MAC:
51 netdev_info(lif->netdev, "Replay failed - %d: mac %pM\n",
54 case IONIC_RX_FILTER_MATCH_MAC_VLAN:
55 netdev_info(lif->netdev, "Replay failed - %d: vlan %d mac %pM\n",
57 le16_to_cpu(ac->vlan.vlan),
66 int ionic_rx_filters_init(struct ionic_lif *lif)
70 spin_lock_init(&lif->rx_filters.lock);
72 for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
73 INIT_HLIST_HEAD(&lif->rx_filters.by_hash[i]);
74 INIT_HLIST_HEAD(&lif->rx_filters.by_id[i]);
80 void ionic_rx_filters_deinit(struct ionic_lif *lif)
82 struct ionic_rx_filter *f;
83 struct hlist_head *head;
84 struct hlist_node *tmp;
87 for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
88 head = &lif->rx_filters.by_id[i];
89 hlist_for_each_entry_safe(f, tmp, head, by_id)
90 ionic_rx_filter_free(lif, f);
94 int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
95 u32 hash, struct ionic_admin_ctx *ctx)
97 struct device *dev = lif->ionic->dev;
98 struct ionic_rx_filter_add_cmd *ac;
99 struct ionic_rx_filter *f;
100 struct hlist_head *head;
103 ac = &ctx->cmd.rx_filter_add;
105 switch (le16_to_cpu(ac->match)) {
106 case IONIC_RX_FILTER_MATCH_VLAN:
107 key = le16_to_cpu(ac->vlan.vlan);
109 case IONIC_RX_FILTER_MATCH_MAC:
110 key = *(u32 *)ac->mac.addr;
112 case IONIC_RX_FILTER_MATCH_MAC_VLAN:
113 key = le16_to_cpu(ac->mac_vlan.vlan);
119 f = devm_kzalloc(dev, sizeof(*f), GFP_KERNEL);
123 f->flow_id = flow_id;
124 f->filter_id = le32_to_cpu(ctx->comp.rx_filter_add.filter_id);
125 f->rxq_index = rxq_index;
126 memcpy(&f->cmd, ac, sizeof(f->cmd));
128 INIT_HLIST_NODE(&f->by_hash);
129 INIT_HLIST_NODE(&f->by_id);
131 spin_lock_bh(&lif->rx_filters.lock);
133 key = hash_32(key, IONIC_RX_FILTER_HASH_BITS);
134 head = &lif->rx_filters.by_hash[key];
135 hlist_add_head(&f->by_hash, head);
137 key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
138 head = &lif->rx_filters.by_id[key];
139 hlist_add_head(&f->by_id, head);
141 spin_unlock_bh(&lif->rx_filters.lock);
146 struct ionic_rx_filter *ionic_rx_filter_by_vlan(struct ionic_lif *lif, u16 vid)
148 struct ionic_rx_filter *f;
149 struct hlist_head *head;
152 key = hash_32(vid, IONIC_RX_FILTER_HASH_BITS);
153 head = &lif->rx_filters.by_hash[key];
155 hlist_for_each_entry(f, head, by_hash) {
156 if (le16_to_cpu(f->cmd.match) != IONIC_RX_FILTER_MATCH_VLAN)
158 if (le16_to_cpu(f->cmd.vlan.vlan) == vid)
165 struct ionic_rx_filter *ionic_rx_filter_by_addr(struct ionic_lif *lif,
168 struct ionic_rx_filter *f;
169 struct hlist_head *head;
172 key = hash_32(*(u32 *)addr, IONIC_RX_FILTER_HASH_BITS);
173 head = &lif->rx_filters.by_hash[key];
175 hlist_for_each_entry(f, head, by_hash) {
176 if (le16_to_cpu(f->cmd.match) != IONIC_RX_FILTER_MATCH_MAC)
178 if (memcmp(addr, f->cmd.mac.addr, ETH_ALEN) == 0)