]> Git Repo - linux.git/blob - drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c
Linux 6.14-rc3
[linux.git] / drivers / net / ethernet / microchip / lan966x / lan966x_vcap_impl.c
1 // SPDX-License-Identifier: GPL-2.0+
2
3 #include "lan966x_main.h"
4 #include "lan966x_vcap_ag_api.h"
5 #include "vcap_api.h"
6 #include "vcap_api_client.h"
7 #include "vcap_api_debugfs.h"
8
9 #define STREAMSIZE (64 * 4)
10
11 #define LAN966X_IS1_LOOKUPS 3
12 #define LAN966X_IS2_LOOKUPS 2
13 #define LAN966X_ES0_LOOKUPS 1
14
15 #define LAN966X_STAT_ESDX_GRN_BYTES 0x300
16 #define LAN966X_STAT_ESDX_GRN_PKTS 0x301
17 #define LAN966X_STAT_ESDX_YEL_BYTES 0x302
18 #define LAN966X_STAT_ESDX_YEL_PKTS 0x303
19
20 static struct lan966x_vcap_inst {
21         enum vcap_type vtype; /* type of vcap */
22         int tgt_inst; /* hardware instance number */
23         int lookups; /* number of lookups in this vcap type */
24         int first_cid; /* first chain id in this vcap */
25         int last_cid; /* last chain id in this vcap */
26         int count; /* number of available addresses */
27         bool ingress; /* is vcap in the ingress path */
28 } lan966x_vcap_inst_cfg[] = {
29         {
30                 .vtype = VCAP_TYPE_ES0,
31                 .tgt_inst = 0,
32                 .lookups = LAN966X_ES0_LOOKUPS,
33                 .first_cid = LAN966X_VCAP_CID_ES0_L0,
34                 .last_cid = LAN966X_VCAP_CID_ES0_MAX,
35                 .count = 64,
36         },
37         {
38                 .vtype = VCAP_TYPE_IS1, /* IS1-0 */
39                 .tgt_inst = 1,
40                 .lookups = LAN966X_IS1_LOOKUPS,
41                 .first_cid = LAN966X_VCAP_CID_IS1_L0,
42                 .last_cid = LAN966X_VCAP_CID_IS1_MAX,
43                 .count = 768,
44                 .ingress = true,
45         },
46         {
47                 .vtype = VCAP_TYPE_IS2, /* IS2-0 */
48                 .tgt_inst = 2,
49                 .lookups = LAN966X_IS2_LOOKUPS,
50                 .first_cid = LAN966X_VCAP_CID_IS2_L0,
51                 .last_cid = LAN966X_VCAP_CID_IS2_MAX,
52                 .count = 256,
53                 .ingress = true,
54         },
55 };
56
57 struct lan966x_vcap_cmd_cb {
58         struct lan966x *lan966x;
59         u32 instance;
60 };
61
62 static u32 lan966x_vcap_read_update_ctrl(const struct lan966x_vcap_cmd_cb *cb)
63 {
64         return lan_rd(cb->lan966x, VCAP_UPDATE_CTRL(cb->instance));
65 }
66
67 static void lan966x_vcap_wait_update(struct lan966x *lan966x, int instance)
68 {
69         const struct lan966x_vcap_cmd_cb cb = { .lan966x = lan966x,
70                                                 .instance = instance };
71         u32 val;
72
73         readx_poll_timeout(lan966x_vcap_read_update_ctrl, &cb, val,
74                            (val & VCAP_UPDATE_CTRL_UPDATE_SHOT) == 0, 10,
75                            100000);
76 }
77
78 static void __lan966x_vcap_range_init(struct lan966x *lan966x,
79                                       struct vcap_admin *admin,
80                                       u32 addr,
81                                       u32 count)
82 {
83         lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) |
84                VCAP_MV_CFG_MV_SIZE_SET(count - 1),
85                lan966x, VCAP_MV_CFG(admin->tgt_inst));
86
87         lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) |
88                VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) |
89                VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) |
90                VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) |
91                VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
92                VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(true) |
93                VCAP_UPDATE_CTRL_UPDATE_SHOT_SET(1),
94                lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
95
96         lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
97 }
98
99 static int lan966x_vcap_is1_cid_to_lookup(int cid)
100 {
101         int lookup = 0;
102
103         if (cid >= LAN966X_VCAP_CID_IS1_L1 &&
104             cid < LAN966X_VCAP_CID_IS1_L2)
105                 lookup = 1;
106         else if (cid >= LAN966X_VCAP_CID_IS1_L2 &&
107                  cid < LAN966X_VCAP_CID_IS1_MAX)
108                 lookup = 2;
109
110         return lookup;
111 }
112
113 static int lan966x_vcap_is2_cid_to_lookup(int cid)
114 {
115         if (cid >= LAN966X_VCAP_CID_IS2_L1 &&
116             cid < LAN966X_VCAP_CID_IS2_MAX)
117                 return 1;
118
119         return 0;
120 }
121
122 /* Return the list of keysets for the vcap port configuration */
123 static int
124 lan966x_vcap_is1_get_port_keysets(struct net_device *ndev, int lookup,
125                                   struct vcap_keyset_list *keysetlist,
126                                   u16 l3_proto)
127 {
128         struct lan966x_port *port = netdev_priv(ndev);
129         struct lan966x *lan966x = port->lan966x;
130         u32 val;
131
132         val = lan_rd(lan966x, ANA_VCAP_S1_CFG(port->chip_port, lookup));
133
134         /* Collect all keysets for the port in a list */
135         if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) {
136                 switch (ANA_VCAP_S1_CFG_KEY_IP4_CFG_GET(val)) {
137                 case VCAP_IS1_PS_IPV4_7TUPLE:
138                         vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE);
139                         break;
140                 case VCAP_IS1_PS_IPV4_5TUPLE_IP4:
141                         vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP4);
142                         break;
143                 case VCAP_IS1_PS_IPV4_NORMAL:
144                         vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL);
145                         break;
146                 }
147         }
148
149         if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) {
150                 switch (ANA_VCAP_S1_CFG_KEY_IP6_CFG_GET(val)) {
151                 case VCAP_IS1_PS_IPV6_NORMAL:
152                 case VCAP_IS1_PS_IPV6_NORMAL_IP6:
153                         vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL);
154                         vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL_IP6);
155                         break;
156                 case VCAP_IS1_PS_IPV6_5TUPLE_IP6:
157                         vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP6);
158                         break;
159                 case VCAP_IS1_PS_IPV6_7TUPLE:
160                         vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE);
161                         break;
162                 case VCAP_IS1_PS_IPV6_5TUPLE_IP4:
163                         vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP4);
164                         break;
165                 case VCAP_IS1_PS_IPV6_DMAC_VID:
166                         vcap_keyset_list_add(keysetlist, VCAP_KFS_DMAC_VID);
167                         break;
168                 }
169         }
170
171         switch (ANA_VCAP_S1_CFG_KEY_OTHER_CFG_GET(val)) {
172         case VCAP_IS1_PS_OTHER_7TUPLE:
173                 vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE);
174                 break;
175         case VCAP_IS1_PS_OTHER_NORMAL:
176                 vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL);
177                 break;
178         }
179
180         return 0;
181 }
182
183 static int
184 lan966x_vcap_is2_get_port_keysets(struct net_device *dev, int lookup,
185                                   struct vcap_keyset_list *keysetlist,
186                                   u16 l3_proto)
187 {
188         struct lan966x_port *port = netdev_priv(dev);
189         struct lan966x *lan966x = port->lan966x;
190         bool found = false;
191         u32 val;
192
193         val = lan_rd(lan966x, ANA_VCAP_S2_CFG(port->chip_port));
194
195         /* Collect all keysets for the port in a list */
196         if (l3_proto == ETH_P_ALL)
197                 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
198
199         if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_SNAP) {
200                 if (ANA_VCAP_S2_CFG_SNAP_DIS_GET(val) & (BIT(0) << lookup))
201                         vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_LLC);
202                 else
203                         vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_SNAP);
204
205                 found = true;
206         }
207
208         if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_CFM) {
209                 if (ANA_VCAP_S2_CFG_OAM_DIS_GET(val) & (BIT(0) << lookup))
210                         vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
211                 else
212                         vcap_keyset_list_add(keysetlist, VCAP_KFS_OAM);
213
214                 found = true;
215         }
216
217         if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) {
218                 if (ANA_VCAP_S2_CFG_ARP_DIS_GET(val) & (BIT(0) << lookup))
219                         vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
220                 else
221                         vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP);
222
223                 found = true;
224         }
225
226         if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) {
227                 if (ANA_VCAP_S2_CFG_IP_OTHER_DIS_GET(val) & (BIT(0) << lookup))
228                         vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
229                 else
230                         vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
231
232                 if (ANA_VCAP_S2_CFG_IP_TCPUDP_DIS_GET(val) & (BIT(0) << lookup))
233                         vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
234                 else
235                         vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
236
237                 found = true;
238         }
239
240         if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) {
241                 switch (ANA_VCAP_S2_CFG_IP6_CFG_GET(val) & (0x3 << lookup)) {
242                 case VCAP_IS2_PS_IPV6_TCPUDP_OTHER:
243                         vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_OTHER);
244                         vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_TCP_UDP);
245                         break;
246                 case VCAP_IS2_PS_IPV6_STD:
247                         vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
248                         break;
249                 case VCAP_IS2_PS_IPV6_IP4_TCPUDP_IP4_OTHER:
250                         vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
251                         vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
252                         break;
253                 case VCAP_IS2_PS_IPV6_MAC_ETYPE:
254                         vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
255                         break;
256                 }
257
258                 found = true;
259         }
260
261         if (!found)
262                 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
263
264         return 0;
265 }
266
267 static enum vcap_keyfield_set
268 lan966x_vcap_validate_keyset(struct net_device *dev,
269                              struct vcap_admin *admin,
270                              struct vcap_rule *rule,
271                              struct vcap_keyset_list *kslist,
272                              u16 l3_proto)
273 {
274         struct vcap_keyset_list keysetlist = {};
275         enum vcap_keyfield_set keysets[10] = {};
276         int lookup;
277         int err;
278
279         if (!kslist || kslist->cnt == 0)
280                 return VCAP_KFS_NO_VALUE;
281
282         keysetlist.max = ARRAY_SIZE(keysets);
283         keysetlist.keysets = keysets;
284
285         switch (admin->vtype) {
286         case VCAP_TYPE_IS1:
287                 lookup = lan966x_vcap_is1_cid_to_lookup(rule->vcap_chain_id);
288                 err = lan966x_vcap_is1_get_port_keysets(dev, lookup, &keysetlist,
289                                                         l3_proto);
290                 break;
291         case VCAP_TYPE_IS2:
292                 lookup = lan966x_vcap_is2_cid_to_lookup(rule->vcap_chain_id);
293                 err = lan966x_vcap_is2_get_port_keysets(dev, lookup, &keysetlist,
294                                                         l3_proto);
295                 break;
296         case VCAP_TYPE_ES0:
297                 return kslist->keysets[0];
298         default:
299                 pr_err("vcap type: %s not supported\n",
300                        lan966x_vcaps[admin->vtype].name);
301                 return VCAP_KFS_NO_VALUE;
302         }
303
304         if (err)
305                 return VCAP_KFS_NO_VALUE;
306
307         /* Check if there is a match and return the match */
308         for (int i = 0; i < kslist->cnt; ++i)
309                 for (int j = 0; j < keysetlist.cnt; ++j)
310                         if (kslist->keysets[i] == keysets[j])
311                                 return kslist->keysets[i];
312
313         return VCAP_KFS_NO_VALUE;
314 }
315
316 static bool lan966x_vcap_is2_is_first_chain(struct vcap_rule *rule)
317 {
318         return (rule->vcap_chain_id >= LAN966X_VCAP_CID_IS2_L0 &&
319                 rule->vcap_chain_id < LAN966X_VCAP_CID_IS2_L1);
320 }
321
322 static void lan966x_vcap_is1_add_default_fields(struct lan966x_port *port,
323                                                 struct vcap_admin *admin,
324                                                 struct vcap_rule *rule)
325 {
326         u32 value, mask;
327         u32 lookup;
328
329         if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK,
330                                   &value, &mask))
331                 vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0,
332                                       ~BIT(port->chip_port));
333
334         lookup = lan966x_vcap_is1_cid_to_lookup(rule->vcap_chain_id);
335         vcap_rule_add_key_u32(rule, VCAP_KF_LOOKUP_INDEX, lookup, 0x3);
336 }
337
338 static void lan966x_vcap_is2_add_default_fields(struct lan966x_port *port,
339                                                 struct vcap_admin *admin,
340                                                 struct vcap_rule *rule)
341 {
342         u32 value, mask;
343
344         if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK,
345                                   &value, &mask))
346                 vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0,
347                                       ~BIT(port->chip_port));
348
349         if (lan966x_vcap_is2_is_first_chain(rule))
350                 vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
351                                       VCAP_BIT_1);
352         else
353                 vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
354                                       VCAP_BIT_0);
355 }
356
357 static void lan966x_vcap_es0_add_default_fields(struct lan966x_port *port,
358                                                 struct vcap_admin *admin,
359                                                 struct vcap_rule *rule)
360 {
361         vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_NO,
362                               port->chip_port, GENMASK(4, 0));
363 }
364
365 static void lan966x_vcap_add_default_fields(struct net_device *dev,
366                                             struct vcap_admin *admin,
367                                             struct vcap_rule *rule)
368 {
369         struct lan966x_port *port = netdev_priv(dev);
370
371         switch (admin->vtype) {
372         case VCAP_TYPE_IS1:
373                 lan966x_vcap_is1_add_default_fields(port, admin, rule);
374                 break;
375         case VCAP_TYPE_IS2:
376                 lan966x_vcap_is2_add_default_fields(port, admin, rule);
377                 break;
378         case VCAP_TYPE_ES0:
379                 lan966x_vcap_es0_add_default_fields(port, admin, rule);
380                 break;
381         default:
382                 pr_err("vcap type: %s not supported\n",
383                        lan966x_vcaps[admin->vtype].name);
384                 break;
385         }
386 }
387
388 static void lan966x_vcap_cache_erase(struct vcap_admin *admin)
389 {
390         memset(admin->cache.keystream, 0, STREAMSIZE);
391         memset(admin->cache.maskstream, 0, STREAMSIZE);
392         memset(admin->cache.actionstream, 0, STREAMSIZE);
393         memset(&admin->cache.counter, 0, sizeof(admin->cache.counter));
394 }
395
396 /* The ESDX counter is only used/incremented if the frame has been classified
397  * with an ISDX > 0 (e.g by a rule in IS0).  This is not mentioned in the
398  * datasheet.
399  */
400 static void lan966x_es0_read_esdx_counter(struct lan966x *lan966x,
401                                           struct vcap_admin *admin, u32 id)
402 {
403         u32 counter;
404
405         id = id & 0xff; /* counter limit */
406         mutex_lock(&lan966x->stats_lock);
407         lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG);
408         counter = lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS)) +
409                   lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS));
410         mutex_unlock(&lan966x->stats_lock);
411         if (counter)
412                 admin->cache.counter = counter;
413 }
414
415 static void lan966x_es0_write_esdx_counter(struct lan966x *lan966x,
416                                            struct vcap_admin *admin, u32 id)
417 {
418         id = id & 0xff; /* counter limit */
419
420         mutex_lock(&lan966x->stats_lock);
421         lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG);
422         lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_BYTES));
423         lan_wr(admin->cache.counter, lan966x,
424                SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS));
425         lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_BYTES));
426         lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS));
427         mutex_unlock(&lan966x->stats_lock);
428 }
429
430 static void lan966x_vcap_cache_write(struct net_device *dev,
431                                      struct vcap_admin *admin,
432                                      enum vcap_selection sel,
433                                      u32 start,
434                                      u32 count)
435 {
436         struct lan966x_port *port = netdev_priv(dev);
437         struct lan966x *lan966x = port->lan966x;
438         u32 *keystr, *mskstr, *actstr;
439
440         keystr = &admin->cache.keystream[start];
441         mskstr = &admin->cache.maskstream[start];
442         actstr = &admin->cache.actionstream[start];
443
444         switch (sel) {
445         case VCAP_SEL_ENTRY:
446                 for (int i = 0; i < count; ++i) {
447                         lan_wr(keystr[i] & mskstr[i], lan966x,
448                                VCAP_ENTRY_DAT(admin->tgt_inst, i));
449                         lan_wr(~mskstr[i], lan966x,
450                                VCAP_MASK_DAT(admin->tgt_inst, i));
451                 }
452                 break;
453         case VCAP_SEL_ACTION:
454                 for (int i = 0; i < count; ++i)
455                         lan_wr(actstr[i], lan966x,
456                                VCAP_ACTION_DAT(admin->tgt_inst, i));
457                 break;
458         case VCAP_SEL_COUNTER:
459                 admin->cache.sticky = admin->cache.counter > 0;
460                 lan_wr(admin->cache.counter, lan966x,
461                        VCAP_CNT_DAT(admin->tgt_inst, 0));
462
463                 if (admin->vtype == VCAP_TYPE_ES0)
464                         lan966x_es0_write_esdx_counter(lan966x, admin, start);
465                 break;
466         default:
467                 break;
468         }
469 }
470
471 static void lan966x_vcap_cache_read(struct net_device *dev,
472                                     struct vcap_admin *admin,
473                                     enum vcap_selection sel,
474                                     u32 start,
475                                     u32 count)
476 {
477         struct lan966x_port *port = netdev_priv(dev);
478         struct lan966x *lan966x = port->lan966x;
479         int instance = admin->tgt_inst;
480         u32 *keystr, *mskstr, *actstr;
481
482         keystr = &admin->cache.keystream[start];
483         mskstr = &admin->cache.maskstream[start];
484         actstr = &admin->cache.actionstream[start];
485
486         if (sel & VCAP_SEL_ENTRY) {
487                 for (int i = 0; i < count; ++i) {
488                         keystr[i] =
489                                 lan_rd(lan966x, VCAP_ENTRY_DAT(instance, i));
490                         mskstr[i] =
491                                 ~lan_rd(lan966x, VCAP_MASK_DAT(instance, i));
492                 }
493         }
494
495         if (sel & VCAP_SEL_ACTION)
496                 for (int i = 0; i < count; ++i)
497                         actstr[i] =
498                                 lan_rd(lan966x, VCAP_ACTION_DAT(instance, i));
499
500         if (sel & VCAP_SEL_COUNTER) {
501                 admin->cache.counter =
502                         lan_rd(lan966x, VCAP_CNT_DAT(instance, 0));
503                 admin->cache.sticky = admin->cache.counter > 0;
504
505                 if (admin->vtype == VCAP_TYPE_ES0)
506                         lan966x_es0_read_esdx_counter(lan966x, admin, start);
507         }
508 }
509
510 static void lan966x_vcap_range_init(struct net_device *dev,
511                                     struct vcap_admin *admin,
512                                     u32 addr,
513                                     u32 count)
514 {
515         struct lan966x_port *port = netdev_priv(dev);
516         struct lan966x *lan966x = port->lan966x;
517
518         __lan966x_vcap_range_init(lan966x, admin, addr, count);
519 }
520
521 static void lan966x_vcap_update(struct net_device *dev,
522                                 struct vcap_admin *admin,
523                                 enum vcap_command cmd,
524                                 enum vcap_selection sel,
525                                 u32 addr)
526 {
527         struct lan966x_port *port = netdev_priv(dev);
528         struct lan966x *lan966x = port->lan966x;
529         bool clear;
530
531         clear = (cmd == VCAP_CMD_INITIALIZE);
532
533         lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) |
534                VCAP_MV_CFG_MV_SIZE_SET(0),
535                lan966x, VCAP_MV_CFG(admin->tgt_inst));
536
537         lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) |
538                VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) |
539                VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) |
540                VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) |
541                VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
542                VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(clear) |
543                VCAP_UPDATE_CTRL_UPDATE_SHOT,
544                lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
545
546         lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
547 }
548
549 static void lan966x_vcap_move(struct net_device *dev,
550                               struct vcap_admin *admin,
551                               u32 addr, int offset, int count)
552 {
553         struct lan966x_port *port = netdev_priv(dev);
554         struct lan966x *lan966x = port->lan966x;
555         enum vcap_command cmd;
556         u16 mv_num_pos;
557         u16 mv_size;
558
559         mv_size = count - 1;
560         if (offset > 0) {
561                 mv_num_pos = offset - 1;
562                 cmd = VCAP_CMD_MOVE_DOWN;
563         } else {
564                 mv_num_pos = -offset - 1;
565                 cmd = VCAP_CMD_MOVE_UP;
566         }
567
568         lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(mv_num_pos) |
569                VCAP_MV_CFG_MV_SIZE_SET(mv_size),
570                lan966x, VCAP_MV_CFG(admin->tgt_inst));
571
572         lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) |
573                VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) |
574                VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) |
575                VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) |
576                VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
577                VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(false) |
578                VCAP_UPDATE_CTRL_UPDATE_SHOT,
579                lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
580
581         lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
582 }
583
584 static const struct vcap_operations lan966x_vcap_ops = {
585         .validate_keyset = lan966x_vcap_validate_keyset,
586         .add_default_fields = lan966x_vcap_add_default_fields,
587         .cache_erase = lan966x_vcap_cache_erase,
588         .cache_write = lan966x_vcap_cache_write,
589         .cache_read = lan966x_vcap_cache_read,
590         .init = lan966x_vcap_range_init,
591         .update = lan966x_vcap_update,
592         .move = lan966x_vcap_move,
593         .port_info = lan966x_vcap_port_info,
594 };
595
596 static void lan966x_vcap_admin_free(struct vcap_admin *admin)
597 {
598         if (!admin)
599                 return;
600
601         kfree(admin->cache.keystream);
602         kfree(admin->cache.maskstream);
603         kfree(admin->cache.actionstream);
604         mutex_destroy(&admin->lock);
605         kfree(admin);
606 }
607
608 static struct vcap_admin *
609 lan966x_vcap_admin_alloc(struct lan966x *lan966x, struct vcap_control *ctrl,
610                          const struct lan966x_vcap_inst *cfg)
611 {
612         struct vcap_admin *admin;
613
614         admin = kzalloc(sizeof(*admin), GFP_KERNEL);
615         if (!admin)
616                 return ERR_PTR(-ENOMEM);
617
618         mutex_init(&admin->lock);
619         INIT_LIST_HEAD(&admin->list);
620         INIT_LIST_HEAD(&admin->rules);
621         INIT_LIST_HEAD(&admin->enabled);
622
623         admin->vtype = cfg->vtype;
624         admin->vinst = 0;
625         admin->ingress = cfg->ingress;
626         admin->w32be = true;
627         admin->tgt_inst = cfg->tgt_inst;
628
629         admin->lookups = cfg->lookups;
630         admin->lookups_per_instance = cfg->lookups;
631
632         admin->first_cid = cfg->first_cid;
633         admin->last_cid = cfg->last_cid;
634
635         admin->cache.keystream = kzalloc(STREAMSIZE, GFP_KERNEL);
636         admin->cache.maskstream = kzalloc(STREAMSIZE, GFP_KERNEL);
637         admin->cache.actionstream = kzalloc(STREAMSIZE, GFP_KERNEL);
638         if (!admin->cache.keystream ||
639             !admin->cache.maskstream ||
640             !admin->cache.actionstream) {
641                 lan966x_vcap_admin_free(admin);
642                 return ERR_PTR(-ENOMEM);
643         }
644
645         return admin;
646 }
647
648 static void lan966x_vcap_block_init(struct lan966x *lan966x,
649                                     struct vcap_admin *admin,
650                                     struct lan966x_vcap_inst *cfg)
651 {
652         admin->first_valid_addr = 0;
653         admin->last_used_addr = cfg->count;
654         admin->last_valid_addr = cfg->count - 1;
655
656         lan_wr(VCAP_CORE_IDX_CORE_IDX_SET(0),
657                lan966x, VCAP_CORE_IDX(admin->tgt_inst));
658         lan_wr(VCAP_CORE_MAP_CORE_MAP_SET(1),
659                lan966x, VCAP_CORE_MAP(admin->tgt_inst));
660
661         __lan966x_vcap_range_init(lan966x, admin, admin->first_valid_addr,
662                                   admin->last_valid_addr -
663                                         admin->first_valid_addr);
664 }
665
666 static void lan966x_vcap_port_key_deselection(struct lan966x *lan966x,
667                                               struct vcap_admin *admin)
668 {
669         u32 val;
670
671         switch (admin->vtype) {
672         case VCAP_TYPE_IS1:
673                 val = ANA_VCAP_S1_CFG_KEY_IP6_CFG_SET(VCAP_IS1_PS_IPV6_5TUPLE_IP6) |
674                       ANA_VCAP_S1_CFG_KEY_IP4_CFG_SET(VCAP_IS1_PS_IPV4_5TUPLE_IP4) |
675                       ANA_VCAP_S1_CFG_KEY_OTHER_CFG_SET(VCAP_IS1_PS_OTHER_NORMAL);
676
677                 for (int p = 0; p < lan966x->num_phys_ports; ++p) {
678                         if (!lan966x->ports[p])
679                                 continue;
680
681                         for (int l = 0; l < LAN966X_IS1_LOOKUPS; ++l)
682                                 lan_wr(val, lan966x, ANA_VCAP_S1_CFG(p, l));
683
684                         lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true),
685                                 ANA_VCAP_CFG_S1_ENA, lan966x,
686                                 ANA_VCAP_CFG(p));
687                 }
688
689                 break;
690         case VCAP_TYPE_IS2:
691                 for (int p = 0; p < lan966x->num_phys_ports; ++p)
692                         lan_wr(0, lan966x, ANA_VCAP_S2_CFG(p));
693
694                 break;
695         case VCAP_TYPE_ES0:
696                 for (int p = 0; p < lan966x->num_phys_ports; ++p)
697                         lan_rmw(REW_PORT_CFG_ES0_EN_SET(false),
698                                 REW_PORT_CFG_ES0_EN, lan966x,
699                                 REW_PORT_CFG(p));
700                 break;
701         default:
702                 pr_err("vcap type: %s not supported\n",
703                        lan966x_vcaps[admin->vtype].name);
704                 break;
705         }
706 }
707
708 int lan966x_vcap_init(struct lan966x *lan966x)
709 {
710         struct lan966x_vcap_inst *cfg;
711         struct vcap_control *ctrl;
712         struct vcap_admin *admin;
713         struct dentry *dir;
714
715         ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
716         if (!ctrl)
717                 return -ENOMEM;
718
719         ctrl->vcaps = lan966x_vcaps;
720         ctrl->stats = &lan966x_vcap_stats;
721         ctrl->ops = &lan966x_vcap_ops;
722
723         INIT_LIST_HEAD(&ctrl->list);
724         for (int i = 0; i < ARRAY_SIZE(lan966x_vcap_inst_cfg); ++i) {
725                 cfg = &lan966x_vcap_inst_cfg[i];
726
727                 admin = lan966x_vcap_admin_alloc(lan966x, ctrl, cfg);
728                 if (IS_ERR(admin))
729                         return PTR_ERR(admin);
730
731                 lan966x_vcap_block_init(lan966x, admin, cfg);
732                 lan966x_vcap_port_key_deselection(lan966x, admin);
733
734                 list_add_tail(&admin->list, &ctrl->list);
735         }
736
737         dir = vcap_debugfs(lan966x->dev, lan966x->debugfs_root, ctrl);
738         for (int p = 0; p < lan966x->num_phys_ports; ++p) {
739                 if (lan966x->ports[p]) {
740                         vcap_port_debugfs(lan966x->dev, dir, ctrl,
741                                           lan966x->ports[p]->dev);
742
743                         lan_rmw(ANA_VCAP_S2_CFG_ENA_SET(true),
744                                 ANA_VCAP_S2_CFG_ENA, lan966x,
745                                 ANA_VCAP_S2_CFG(lan966x->ports[p]->chip_port));
746
747                         lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true),
748                                 ANA_VCAP_CFG_S1_ENA, lan966x,
749                                 ANA_VCAP_CFG(lan966x->ports[p]->chip_port));
750
751                         lan_rmw(REW_PORT_CFG_ES0_EN_SET(true),
752                                 REW_PORT_CFG_ES0_EN, lan966x,
753                                 REW_PORT_CFG(lan966x->ports[p]->chip_port));
754                 }
755         }
756
757         /* Statistics: Use ESDX from ES0 if hit, otherwise no counting */
758         lan_rmw(REW_STAT_CFG_STAT_MODE_SET(1),
759                 REW_STAT_CFG_STAT_MODE, lan966x,
760                 REW_STAT_CFG);
761
762         lan966x->vcap_ctrl = ctrl;
763
764         return 0;
765 }
766
767 void lan966x_vcap_deinit(struct lan966x *lan966x)
768 {
769         struct vcap_admin *admin, *admin_next;
770         struct vcap_control *ctrl;
771
772         ctrl = lan966x->vcap_ctrl;
773         if (!ctrl)
774                 return;
775
776         list_for_each_entry_safe(admin, admin_next, &ctrl->list, list) {
777                 lan966x_vcap_port_key_deselection(lan966x, admin);
778                 vcap_del_rules(ctrl, admin);
779                 list_del(&admin->list);
780                 lan966x_vcap_admin_free(admin);
781         }
782
783         kfree(ctrl);
784 }
This page took 0.070531 seconds and 4 git commands to generate.