1
2
3
4#include <linux/netdevice.h>
5#include <linux/dynamic_debug.h>
6#include <linux/etherdevice.h>
7
8#include "ionic.h"
9#include "ionic_lif.h"
10#include "ionic_rx_filter.h"
11
12void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f)
13{
14 struct device *dev = lif->ionic->dev;
15
16 hlist_del(&f->by_id);
17 hlist_del(&f->by_hash);
18 devm_kfree(dev, f);
19}
20
21void ionic_rx_filter_replay(struct ionic_lif *lif)
22{
23 struct ionic_rx_filter_add_cmd *ac;
24 struct hlist_head new_id_list;
25 struct ionic_admin_ctx ctx;
26 struct ionic_rx_filter *f;
27 struct hlist_head *head;
28 struct hlist_node *tmp;
29 unsigned int key;
30 unsigned int i;
31 int err;
32
33 INIT_HLIST_HEAD(&new_id_list);
34 ac = &ctx.cmd.rx_filter_add;
35
36 for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
37 head = &lif->rx_filters.by_id[i];
38 hlist_for_each_entry_safe(f, tmp, head, by_id) {
39 ctx.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work);
40 memcpy(ac, &f->cmd, sizeof(f->cmd));
41 dev_dbg(&lif->netdev->dev, "replay filter command:\n");
42 dynamic_hex_dump("cmd ", DUMP_PREFIX_OFFSET, 16, 1,
43 &ctx.cmd, sizeof(ctx.cmd), true);
44
45 err = ionic_adminq_post_wait(lif, &ctx);
46 if (err) {
47 switch (le16_to_cpu(ac->match)) {
48 case IONIC_RX_FILTER_MATCH_VLAN:
49 netdev_info(lif->netdev, "Replay failed - %d: vlan %d\n",
50 err,
51 le16_to_cpu(ac->vlan.vlan));
52 break;
53 case IONIC_RX_FILTER_MATCH_MAC:
54 netdev_info(lif->netdev, "Replay failed - %d: mac %pM\n",
55 err, ac->mac.addr);
56 break;
57 case IONIC_RX_FILTER_MATCH_MAC_VLAN:
58 netdev_info(lif->netdev, "Replay failed - %d: vlan %d mac %pM\n",
59 err,
60 le16_to_cpu(ac->vlan.vlan),
61 ac->mac.addr);
62 break;
63 }
64 spin_lock_bh(&lif->rx_filters.lock);
65 ionic_rx_filter_free(lif, f);
66 spin_unlock_bh(&lif->rx_filters.lock);
67
68 continue;
69 }
70
71
72 spin_lock_bh(&lif->rx_filters.lock);
73 hlist_del(&f->by_id);
74 spin_unlock_bh(&lif->rx_filters.lock);
75 f->filter_id = le32_to_cpu(ctx.comp.rx_filter_add.filter_id);
76 hlist_add_head(&f->by_id, &new_id_list);
77 }
78 }
79
80
81 spin_lock_bh(&lif->rx_filters.lock);
82 hlist_for_each_entry_safe(f, tmp, &new_id_list, by_id) {
83 key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
84 head = &lif->rx_filters.by_id[key];
85 hlist_add_head(&f->by_id, head);
86 }
87 spin_unlock_bh(&lif->rx_filters.lock);
88}
89
90int ionic_rx_filters_init(struct ionic_lif *lif)
91{
92 unsigned int i;
93
94 spin_lock_init(&lif->rx_filters.lock);
95
96 spin_lock_bh(&lif->rx_filters.lock);
97 for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
98 INIT_HLIST_HEAD(&lif->rx_filters.by_hash[i]);
99 INIT_HLIST_HEAD(&lif->rx_filters.by_id[i]);
100 }
101 spin_unlock_bh(&lif->rx_filters.lock);
102
103 return 0;
104}
105
106void ionic_rx_filters_deinit(struct ionic_lif *lif)
107{
108 struct ionic_rx_filter *f;
109 struct hlist_head *head;
110 struct hlist_node *tmp;
111 unsigned int i;
112
113 spin_lock_bh(&lif->rx_filters.lock);
114 for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
115 head = &lif->rx_filters.by_id[i];
116 hlist_for_each_entry_safe(f, tmp, head, by_id)
117 ionic_rx_filter_free(lif, f);
118 }
119 spin_unlock_bh(&lif->rx_filters.lock);
120}
121
122int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
123 u32 hash, struct ionic_admin_ctx *ctx)
124{
125 struct device *dev = lif->ionic->dev;
126 struct ionic_rx_filter_add_cmd *ac;
127 struct ionic_rx_filter *f;
128 struct hlist_head *head;
129 unsigned int key;
130
131 ac = &ctx->cmd.rx_filter_add;
132
133 switch (le16_to_cpu(ac->match)) {
134 case IONIC_RX_FILTER_MATCH_VLAN:
135 key = le16_to_cpu(ac->vlan.vlan);
136 break;
137 case IONIC_RX_FILTER_MATCH_MAC:
138 key = *(u32 *)ac->mac.addr;
139 break;
140 case IONIC_RX_FILTER_MATCH_MAC_VLAN:
141 key = le16_to_cpu(ac->mac_vlan.vlan);
142 break;
143 case IONIC_RX_FILTER_STEER_PKTCLASS:
144 key = 0;
145 break;
146 default:
147 return -EINVAL;
148 }
149
150 f = devm_kzalloc(dev, sizeof(*f), GFP_KERNEL);
151 if (!f)
152 return -ENOMEM;
153
154 f->flow_id = flow_id;
155 f->filter_id = le32_to_cpu(ctx->comp.rx_filter_add.filter_id);
156 f->rxq_index = rxq_index;
157 memcpy(&f->cmd, ac, sizeof(f->cmd));
158 netdev_dbg(lif->netdev, "rx_filter add filter_id %d\n", f->filter_id);
159
160 INIT_HLIST_NODE(&f->by_hash);
161 INIT_HLIST_NODE(&f->by_id);
162
163 spin_lock_bh(&lif->rx_filters.lock);
164
165 key = hash_32(key, IONIC_RX_FILTER_HASH_BITS);
166 head = &lif->rx_filters.by_hash[key];
167 hlist_add_head(&f->by_hash, head);
168
169 key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
170 head = &lif->rx_filters.by_id[key];
171 hlist_add_head(&f->by_id, head);
172
173 spin_unlock_bh(&lif->rx_filters.lock);
174
175 return 0;
176}
177
178struct ionic_rx_filter *ionic_rx_filter_by_vlan(struct ionic_lif *lif, u16 vid)
179{
180 struct ionic_rx_filter *f;
181 struct hlist_head *head;
182 unsigned int key;
183
184 key = hash_32(vid, IONIC_RX_FILTER_HASH_BITS);
185 head = &lif->rx_filters.by_hash[key];
186
187 hlist_for_each_entry(f, head, by_hash) {
188 if (le16_to_cpu(f->cmd.match) != IONIC_RX_FILTER_MATCH_VLAN)
189 continue;
190 if (le16_to_cpu(f->cmd.vlan.vlan) == vid)
191 return f;
192 }
193
194 return NULL;
195}
196
197struct ionic_rx_filter *ionic_rx_filter_by_addr(struct ionic_lif *lif,
198 const u8 *addr)
199{
200 struct ionic_rx_filter *f;
201 struct hlist_head *head;
202 unsigned int key;
203
204 key = hash_32(*(u32 *)addr, IONIC_RX_FILTER_HASH_BITS);
205 head = &lif->rx_filters.by_hash[key];
206
207 hlist_for_each_entry(f, head, by_hash) {
208 if (le16_to_cpu(f->cmd.match) != IONIC_RX_FILTER_MATCH_MAC)
209 continue;
210 if (memcmp(addr, f->cmd.mac.addr, ETH_ALEN) == 0)
211 return f;
212 }
213
214 return NULL;
215}
216
217struct ionic_rx_filter *ionic_rx_filter_rxsteer(struct ionic_lif *lif)
218{
219 struct ionic_rx_filter *f;
220 struct hlist_head *head;
221 unsigned int key;
222
223 key = hash_32(0, IONIC_RX_FILTER_HASH_BITS);
224 head = &lif->rx_filters.by_hash[key];
225
226 hlist_for_each_entry(f, head, by_hash) {
227 if (le16_to_cpu(f->cmd.match) != IONIC_RX_FILTER_STEER_PKTCLASS)
228 continue;
229 return f;
230 }
231
232 return NULL;
233}
234