forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
....@@ -36,6 +36,7 @@
3636 #include <net/tc_act/tc_mirred.h>
3737
3838 #include "cxgb4.h"
39
+#include "cxgb4_filter.h"
3940 #include "cxgb4_tc_u32_parse.h"
4041 #include "cxgb4_tc_u32.h"
4142
....@@ -148,14 +149,16 @@
148149 int cxgb4_config_knode(struct net_device *dev, struct tc_cls_u32_offload *cls)
149150 {
150151 const struct cxgb4_match_field *start, *link_start = NULL;
152
+ struct netlink_ext_ack *extack = cls->common.extack;
151153 struct adapter *adapter = netdev2adap(dev);
152154 __be16 protocol = cls->common.protocol;
153155 struct ch_filter_specification fs;
154156 struct cxgb4_tc_u32_table *t;
155157 struct cxgb4_link *link;
156
- unsigned int filter_id;
157158 u32 uhtid, link_uhtid;
158159 bool is_ipv6 = false;
160
+ u8 inet_family;
161
+ int filter_id;
159162 int ret;
160163
161164 if (!can_tc_u32_offload(dev))
....@@ -164,14 +167,18 @@
164167 if (protocol != htons(ETH_P_IP) && protocol != htons(ETH_P_IPV6))
165168 return -EOPNOTSUPP;
166169
167
- /* Fetch the location to insert the filter. */
168
- filter_id = cls->knode.handle & 0xFFFFF;
170
+ inet_family = (protocol == htons(ETH_P_IPV6)) ? PF_INET6 : PF_INET;
169171
170
- if (filter_id > adapter->tids.nftids) {
171
- dev_err(adapter->pdev_dev,
172
- "Location %d out of range for insertion. Max: %d\n",
173
- filter_id, adapter->tids.nftids);
174
- return -ERANGE;
172
+ /* Get a free filter entry TID, where we can insert this new
173
+ * rule. Only insert rule if its prio doesn't conflict with
174
+ * existing rules.
175
+ */
176
+ filter_id = cxgb4_get_free_ftid(dev, inet_family, false,
177
+ TC_U32_NODE(cls->knode.handle));
178
+ if (filter_id < 0) {
179
+ NL_SET_ERR_MSG_MOD(extack,
180
+ "No free LETCAM index available");
181
+ return -ENOMEM;
175182 }
176183
177184 t = adapter->tc_u32;
....@@ -189,6 +196,11 @@
189196 return -EINVAL;
190197
191198 memset(&fs, 0, sizeof(fs));
199
+
200
+ if (filter_id < adapter->tids.nhpftids)
201
+ fs.prio = 1;
202
+ fs.tc_prio = cls->common.prio;
203
+ fs.tc_cookie = cls->knode.handle;
192204
193205 if (protocol == htons(ETH_P_IPV6)) {
194206 start = cxgb4_ipv6_fields;
....@@ -343,21 +355,67 @@
343355 unsigned int filter_id, max_tids, i, j;
344356 struct cxgb4_link *link = NULL;
345357 struct cxgb4_tc_u32_table *t;
358
+ struct filter_entry *f;
359
+ bool found = false;
346360 u32 handle, uhtid;
361
+ u8 nslots;
347362 int ret;
348363
349364 if (!can_tc_u32_offload(dev))
350365 return -EOPNOTSUPP;
351366
352367 /* Fetch the location to delete the filter. */
353
- filter_id = cls->knode.handle & 0xFFFFF;
368
+ max_tids = adapter->tids.nhpftids + adapter->tids.nftids;
354369
355
- if (filter_id > adapter->tids.nftids) {
356
- dev_err(adapter->pdev_dev,
357
- "Location %d out of range for deletion. Max: %d\n",
358
- filter_id, adapter->tids.nftids);
359
- return -ERANGE;
370
+ spin_lock_bh(&adapter->tids.ftid_lock);
371
+ filter_id = 0;
372
+ while (filter_id < max_tids) {
373
+ if (filter_id < adapter->tids.nhpftids) {
374
+ i = filter_id;
375
+ f = &adapter->tids.hpftid_tab[i];
376
+ if (f->valid && f->fs.tc_cookie == cls->knode.handle) {
377
+ found = true;
378
+ break;
379
+ }
380
+
381
+ i = find_next_bit(adapter->tids.hpftid_bmap,
382
+ adapter->tids.nhpftids, i + 1);
383
+ if (i >= adapter->tids.nhpftids) {
384
+ filter_id = adapter->tids.nhpftids;
385
+ continue;
386
+ }
387
+
388
+ filter_id = i;
389
+ } else {
390
+ i = filter_id - adapter->tids.nhpftids;
391
+ f = &adapter->tids.ftid_tab[i];
392
+ if (f->valid && f->fs.tc_cookie == cls->knode.handle) {
393
+ found = true;
394
+ break;
395
+ }
396
+
397
+ i = find_next_bit(adapter->tids.ftid_bmap,
398
+ adapter->tids.nftids, i + 1);
399
+ if (i >= adapter->tids.nftids)
400
+ break;
401
+
402
+ filter_id = i + adapter->tids.nhpftids;
403
+ }
404
+
405
+ nslots = 0;
406
+ if (f->fs.type) {
407
+ nslots++;
408
+ if (CHELSIO_CHIP_VERSION(adapter->params.chip) <
409
+ CHELSIO_T6)
410
+ nslots += 2;
411
+ }
412
+
413
+ filter_id += nslots;
360414 }
415
+ spin_unlock_bh(&adapter->tids.ftid_lock);
416
+
417
+ if (!found)
418
+ return -ERANGE;
361419
362420 t = adapter->tc_u32;
363421 handle = cls->knode.handle;
....@@ -389,7 +447,6 @@
389447 /* If a link is being deleted, then delete all filters
390448 * associated with the link.
391449 */
392
- max_tids = adapter->tids.nftids;
393450 for (i = 0; i < t->size; i++) {
394451 link = &t->table[i];
395452
....@@ -437,15 +494,14 @@
437494
438495 struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap)
439496 {
440
- unsigned int max_tids = adap->tids.nftids;
497
+ unsigned int max_tids = adap->tids.nftids + adap->tids.nhpftids;
441498 struct cxgb4_tc_u32_table *t;
442499 unsigned int i;
443500
444501 if (!max_tids)
445502 return NULL;
446503
447
- t = kvzalloc(sizeof(*t) +
448
- (max_tids * sizeof(struct cxgb4_link)), GFP_KERNEL);
504
+ t = kvzalloc(struct_size(t, table, max_tids), GFP_KERNEL);
449505 if (!t)
450506 return NULL;
451507