Merge tag 'pinctrl-v5.8-4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[linux-2.6-microblaze.git] / drivers / net / ethernet / chelsio / cxgb4 / cxgb4_tc_u32.c
1 /*
2  * This file is part of the Chelsio T4 Ethernet driver for Linux.
3  *
4  * Copyright (c) 2016 Chelsio Communications, Inc. All rights reserved.
5  *
6  * This software is available to you under a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * OpenIB.org BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32  * SOFTWARE.
33  */
34
35 #include <net/tc_act/tc_gact.h>
36 #include <net/tc_act/tc_mirred.h>
37
38 #include "cxgb4.h"
39 #include "cxgb4_filter.h"
40 #include "cxgb4_tc_u32_parse.h"
41 #include "cxgb4_tc_u32.h"
42
43 /* Fill ch_filter_specification with parsed match value/mask pair. */
44 static int fill_match_fields(struct adapter *adap,
45                              struct ch_filter_specification *fs,
46                              struct tc_cls_u32_offload *cls,
47                              const struct cxgb4_match_field *entry,
48                              bool next_header)
49 {
50         unsigned int i, j;
51         __be32 val, mask;
52         int off, err;
53         bool found;
54
55         for (i = 0; i < cls->knode.sel->nkeys; i++) {
56                 off = cls->knode.sel->keys[i].off;
57                 val = cls->knode.sel->keys[i].val;
58                 mask = cls->knode.sel->keys[i].mask;
59
60                 if (next_header) {
61                         /* For next headers, parse only keys with offmask */
62                         if (!cls->knode.sel->keys[i].offmask)
63                                 continue;
64                 } else {
65                         /* For the remaining, parse only keys without offmask */
66                         if (cls->knode.sel->keys[i].offmask)
67                                 continue;
68                 }
69
70                 found = false;
71
72                 for (j = 0; entry[j].val; j++) {
73                         if (off == entry[j].off) {
74                                 found = true;
75                                 err = entry[j].val(fs, val, mask);
76                                 if (err)
77                                         return err;
78                                 break;
79                         }
80                 }
81
82                 if (!found)
83                         return -EINVAL;
84         }
85
86         return 0;
87 }
88
89 /* Fill ch_filter_specification with parsed action. */
90 static int fill_action_fields(struct adapter *adap,
91                               struct ch_filter_specification *fs,
92                               struct tc_cls_u32_offload *cls)
93 {
94         unsigned int num_actions = 0;
95         const struct tc_action *a;
96         struct tcf_exts *exts;
97         int i;
98
99         exts = cls->knode.exts;
100         if (!tcf_exts_has_actions(exts))
101                 return -EINVAL;
102
103         tcf_exts_for_each_action(i, a, exts) {
104                 /* Don't allow more than one action per rule. */
105                 if (num_actions)
106                         return -EINVAL;
107
108                 /* Drop in hardware. */
109                 if (is_tcf_gact_shot(a)) {
110                         fs->action = FILTER_DROP;
111                         num_actions++;
112                         continue;
113                 }
114
115                 /* Re-direct to specified port in hardware. */
116                 if (is_tcf_mirred_egress_redirect(a)) {
117                         struct net_device *n_dev, *target_dev;
118                         bool found = false;
119                         unsigned int i;
120
121                         target_dev = tcf_mirred_dev(a);
122                         for_each_port(adap, i) {
123                                 n_dev = adap->port[i];
124                                 if (target_dev == n_dev) {
125                                         fs->action = FILTER_SWITCH;
126                                         fs->eport = i;
127                                         found = true;
128                                         break;
129                                 }
130                         }
131
132                         /* Interface doesn't belong to any port of
133                          * the underlying hardware.
134                          */
135                         if (!found)
136                                 return -EINVAL;
137
138                         num_actions++;
139                         continue;
140                 }
141
142                 /* Un-supported action. */
143                 return -EINVAL;
144         }
145
146         return 0;
147 }
148
149 int cxgb4_config_knode(struct net_device *dev, struct tc_cls_u32_offload *cls)
150 {
151         const struct cxgb4_match_field *start, *link_start = NULL;
152         struct netlink_ext_ack *extack = cls->common.extack;
153         struct adapter *adapter = netdev2adap(dev);
154         __be16 protocol = cls->common.protocol;
155         struct ch_filter_specification fs;
156         struct cxgb4_tc_u32_table *t;
157         struct cxgb4_link *link;
158         u32 uhtid, link_uhtid;
159         bool is_ipv6 = false;
160         u8 inet_family;
161         int filter_id;
162         int ret;
163
164         if (!can_tc_u32_offload(dev))
165                 return -EOPNOTSUPP;
166
167         if (protocol != htons(ETH_P_IP) && protocol != htons(ETH_P_IPV6))
168                 return -EOPNOTSUPP;
169
170         inet_family = (protocol == htons(ETH_P_IPV6)) ? PF_INET6 : PF_INET;
171
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;
182         }
183
184         t = adapter->tc_u32;
185         uhtid = TC_U32_USERHTID(cls->knode.handle);
186         link_uhtid = TC_U32_USERHTID(cls->knode.link_handle);
187
188         /* Ensure that uhtid is either root u32 (i.e. 0x800)
189          * or a a valid linked bucket.
190          */
191         if (uhtid != 0x800 && uhtid >= t->size)
192                 return -EINVAL;
193
194         /* Ensure link handle uhtid is sane, if specified. */
195         if (link_uhtid >= t->size)
196                 return -EINVAL;
197
198         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;
204
205         if (protocol == htons(ETH_P_IPV6)) {
206                 start = cxgb4_ipv6_fields;
207                 is_ipv6 = true;
208         } else {
209                 start = cxgb4_ipv4_fields;
210                 is_ipv6 = false;
211         }
212
213         if (uhtid != 0x800) {
214                 /* Link must exist from root node before insertion. */
215                 if (!t->table[uhtid - 1].link_handle)
216                         return -EINVAL;
217
218                 /* Link must have a valid supported next header. */
219                 link_start = t->table[uhtid - 1].match_field;
220                 if (!link_start)
221                         return -EINVAL;
222         }
223
224         /* Parse links and record them for subsequent jumps to valid
225          * next headers.
226          */
227         if (link_uhtid) {
228                 const struct cxgb4_next_header *next;
229                 bool found = false;
230                 unsigned int i, j;
231                 __be32 val, mask;
232                 int off;
233
234                 if (t->table[link_uhtid - 1].link_handle) {
235                         dev_err(adapter->pdev_dev,
236                                 "Link handle exists for: 0x%x\n",
237                                 link_uhtid);
238                         return -EINVAL;
239                 }
240
241                 next = is_ipv6 ? cxgb4_ipv6_jumps : cxgb4_ipv4_jumps;
242
243                 /* Try to find matches that allow jumps to next header. */
244                 for (i = 0; next[i].jump; i++) {
245                         if (next[i].sel.offoff != cls->knode.sel->offoff ||
246                             next[i].sel.offshift != cls->knode.sel->offshift ||
247                             next[i].sel.offmask != cls->knode.sel->offmask ||
248                             next[i].sel.off != cls->knode.sel->off)
249                                 continue;
250
251                         /* Found a possible candidate.  Find a key that
252                          * matches the corresponding offset, value, and
253                          * mask to jump to next header.
254                          */
255                         for (j = 0; j < cls->knode.sel->nkeys; j++) {
256                                 off = cls->knode.sel->keys[j].off;
257                                 val = cls->knode.sel->keys[j].val;
258                                 mask = cls->knode.sel->keys[j].mask;
259
260                                 if (next[i].key.off == off &&
261                                     next[i].key.val == val &&
262                                     next[i].key.mask == mask) {
263                                         found = true;
264                                         break;
265                                 }
266                         }
267
268                         if (!found)
269                                 continue; /* Try next candidate. */
270
271                         /* Candidate to jump to next header found.
272                          * Translate all keys to internal specification
273                          * and store them in jump table. This spec is copied
274                          * later to set the actual filters.
275                          */
276                         ret = fill_match_fields(adapter, &fs, cls,
277                                                 start, false);
278                         if (ret)
279                                 goto out;
280
281                         link = &t->table[link_uhtid - 1];
282                         link->match_field = next[i].jump;
283                         link->link_handle = cls->knode.handle;
284                         memcpy(&link->fs, &fs, sizeof(fs));
285                         break;
286                 }
287
288                 /* No candidate found to jump to next header. */
289                 if (!found)
290                         return -EINVAL;
291
292                 return 0;
293         }
294
295         /* Fill ch_filter_specification match fields to be shipped to hardware.
296          * Copy the linked spec (if any) first.  And then update the spec as
297          * needed.
298          */
299         if (uhtid != 0x800 && t->table[uhtid - 1].link_handle) {
300                 /* Copy linked ch_filter_specification */
301                 memcpy(&fs, &t->table[uhtid - 1].fs, sizeof(fs));
302                 ret = fill_match_fields(adapter, &fs, cls,
303                                         link_start, true);
304                 if (ret)
305                         goto out;
306         }
307
308         ret = fill_match_fields(adapter, &fs, cls, start, false);
309         if (ret)
310                 goto out;
311
312         /* Fill ch_filter_specification action fields to be shipped to
313          * hardware.
314          */
315         ret = fill_action_fields(adapter, &fs, cls);
316         if (ret)
317                 goto out;
318
319         /* The filter spec has been completely built from the info
320          * provided from u32.  We now set some default fields in the
321          * spec for sanity.
322          */
323
324         /* Match only packets coming from the ingress port where this
325          * filter will be created.
326          */
327         fs.val.iport = netdev2pinfo(dev)->port_id;
328         fs.mask.iport = ~0;
329
330         /* Enable filter hit counts. */
331         fs.hitcnts = 1;
332
333         /* Set type of filter - IPv6 or IPv4 */
334         fs.type = is_ipv6 ? 1 : 0;
335
336         /* Set the filter */
337         ret = cxgb4_set_filter(dev, filter_id, &fs);
338         if (ret)
339                 goto out;
340
341         /* If this is a linked bucket, then set the corresponding
342          * entry in the bitmap to mark it as belonging to this linked
343          * bucket.
344          */
345         if (uhtid != 0x800 && t->table[uhtid - 1].link_handle)
346                 set_bit(filter_id, t->table[uhtid - 1].tid_map);
347
348 out:
349         return ret;
350 }
351
352 int cxgb4_delete_knode(struct net_device *dev, struct tc_cls_u32_offload *cls)
353 {
354         struct adapter *adapter = netdev2adap(dev);
355         unsigned int filter_id, max_tids, i, j;
356         struct cxgb4_link *link = NULL;
357         struct cxgb4_tc_u32_table *t;
358         struct filter_entry *f;
359         bool found = false;
360         u32 handle, uhtid;
361         u8 nslots;
362         int ret;
363
364         if (!can_tc_u32_offload(dev))
365                 return -EOPNOTSUPP;
366
367         /* Fetch the location to delete the filter. */
368         max_tids = adapter->tids.nhpftids + adapter->tids.nftids;
369
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;
414         }
415         spin_unlock_bh(&adapter->tids.ftid_lock);
416
417         if (!found)
418                 return -ERANGE;
419
420         t = adapter->tc_u32;
421         handle = cls->knode.handle;
422         uhtid = TC_U32_USERHTID(cls->knode.handle);
423
424         /* Ensure that uhtid is either root u32 (i.e. 0x800)
425          * or a a valid linked bucket.
426          */
427         if (uhtid != 0x800 && uhtid >= t->size)
428                 return -EINVAL;
429
430         /* Delete the specified filter */
431         if (uhtid != 0x800) {
432                 link = &t->table[uhtid - 1];
433                 if (!link->link_handle)
434                         return -EINVAL;
435
436                 if (!test_bit(filter_id, link->tid_map))
437                         return -EINVAL;
438         }
439
440         ret = cxgb4_del_filter(dev, filter_id, NULL);
441         if (ret)
442                 goto out;
443
444         if (link)
445                 clear_bit(filter_id, link->tid_map);
446
447         /* If a link is being deleted, then delete all filters
448          * associated with the link.
449          */
450         for (i = 0; i < t->size; i++) {
451                 link = &t->table[i];
452
453                 if (link->link_handle == handle) {
454                         for (j = 0; j < max_tids; j++) {
455                                 if (!test_bit(j, link->tid_map))
456                                         continue;
457
458                                 ret = __cxgb4_del_filter(dev, j, NULL, NULL);
459                                 if (ret)
460                                         goto out;
461
462                                 clear_bit(j, link->tid_map);
463                         }
464
465                         /* Clear the link state */
466                         link->match_field = NULL;
467                         link->link_handle = 0;
468                         memset(&link->fs, 0, sizeof(link->fs));
469                         break;
470                 }
471         }
472
473 out:
474         return ret;
475 }
476
477 void cxgb4_cleanup_tc_u32(struct adapter *adap)
478 {
479         struct cxgb4_tc_u32_table *t;
480         unsigned int i;
481
482         if (!adap->tc_u32)
483                 return;
484
485         /* Free up all allocated memory. */
486         t = adap->tc_u32;
487         for (i = 0; i < t->size; i++) {
488                 struct cxgb4_link *link = &t->table[i];
489
490                 kvfree(link->tid_map);
491         }
492         kvfree(adap->tc_u32);
493 }
494
495 struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap)
496 {
497         unsigned int max_tids = adap->tids.nftids + adap->tids.nhpftids;
498         struct cxgb4_tc_u32_table *t;
499         unsigned int i;
500
501         if (!max_tids)
502                 return NULL;
503
504         t = kvzalloc(struct_size(t, table, max_tids), GFP_KERNEL);
505         if (!t)
506                 return NULL;
507
508         t->size = max_tids;
509
510         for (i = 0; i < t->size; i++) {
511                 struct cxgb4_link *link = &t->table[i];
512                 unsigned int bmap_size;
513
514                 bmap_size = BITS_TO_LONGS(max_tids);
515                 link->tid_map = kvcalloc(bmap_size, sizeof(unsigned long),
516                                          GFP_KERNEL);
517                 if (!link->tid_map)
518                         goto out_no_mem;
519                 bitmap_zero(link->tid_map, max_tids);
520         }
521
522         return t;
523
524 out_no_mem:
525         for (i = 0; i < t->size; i++) {
526                 struct cxgb4_link *link = &t->table[i];
527
528                 if (link->tid_map)
529                         kvfree(link->tid_map);
530         }
531
532         if (t)
533                 kvfree(t);
534
535         return NULL;
536 }