1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
3
4 #include <linux/etherdevice.h>
5 #include <linux/if_bridge.h>
6 #include <linux/ethtool.h>
7 #include <linux/list.h>
8
9 #include "prestera.h"
10 #include "prestera_hw.h"
11 #include "prestera_acl.h"
12
13 #define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
14
15 #define PRESTERA_MIN_MTU 64
16
17 enum prestera_cmd_type_t {
18 PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1,
19 PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2,
20
21 PRESTERA_CMD_TYPE_PORT_ATTR_SET = 0x100,
22 PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101,
23 PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110,
24
25 PRESTERA_CMD_TYPE_VLAN_CREATE = 0x200,
26 PRESTERA_CMD_TYPE_VLAN_DELETE = 0x201,
27 PRESTERA_CMD_TYPE_VLAN_PORT_SET = 0x202,
28 PRESTERA_CMD_TYPE_VLAN_PVID_SET = 0x203,
29
30 PRESTERA_CMD_TYPE_FDB_ADD = 0x300,
31 PRESTERA_CMD_TYPE_FDB_DELETE = 0x301,
32 PRESTERA_CMD_TYPE_FDB_FLUSH_PORT = 0x310,
33 PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN = 0x311,
34 PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN = 0x312,
35
36 PRESTERA_CMD_TYPE_BRIDGE_CREATE = 0x400,
37 PRESTERA_CMD_TYPE_BRIDGE_DELETE = 0x401,
38 PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD = 0x402,
39 PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE = 0x403,
40
41 PRESTERA_CMD_TYPE_ACL_RULE_ADD = 0x500,
42 PRESTERA_CMD_TYPE_ACL_RULE_DELETE = 0x501,
43 PRESTERA_CMD_TYPE_ACL_RULE_STATS_GET = 0x510,
44 PRESTERA_CMD_TYPE_ACL_RULESET_CREATE = 0x520,
45 PRESTERA_CMD_TYPE_ACL_RULESET_DELETE = 0x521,
46 PRESTERA_CMD_TYPE_ACL_PORT_BIND = 0x530,
47 PRESTERA_CMD_TYPE_ACL_PORT_UNBIND = 0x531,
48
49 PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
50
51 PRESTERA_CMD_TYPE_LAG_MEMBER_ADD = 0x900,
52 PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE = 0x901,
53 PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE = 0x902,
54 PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE = 0x903,
55
56 PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
57
58 PRESTERA_CMD_TYPE_SPAN_GET = 0x1100,
59 PRESTERA_CMD_TYPE_SPAN_BIND = 0x1101,
60 PRESTERA_CMD_TYPE_SPAN_UNBIND = 0x1102,
61 PRESTERA_CMD_TYPE_SPAN_RELEASE = 0x1103,
62
63 PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET = 0x2000,
64
65 PRESTERA_CMD_TYPE_ACK = 0x10000,
66 PRESTERA_CMD_TYPE_MAX
67 };
68
69 enum {
70 PRESTERA_CMD_PORT_ATTR_ADMIN_STATE = 1,
71 PRESTERA_CMD_PORT_ATTR_MTU = 3,
72 PRESTERA_CMD_PORT_ATTR_MAC = 4,
73 PRESTERA_CMD_PORT_ATTR_SPEED = 5,
74 PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6,
75 PRESTERA_CMD_PORT_ATTR_LEARNING = 7,
76 PRESTERA_CMD_PORT_ATTR_FLOOD = 8,
77 PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9,
78 PRESTERA_CMD_PORT_ATTR_PHY_MODE = 12,
79 PRESTERA_CMD_PORT_ATTR_TYPE = 13,
80 PRESTERA_CMD_PORT_ATTR_STATS = 17,
81 PRESTERA_CMD_PORT_ATTR_MAC_AUTONEG_RESTART = 18,
82 PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART = 19,
83 PRESTERA_CMD_PORT_ATTR_MAC_MODE = 22,
84 };
85
86 enum {
87 PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
88 PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
89 };
90
91 enum {
92 PRESTERA_CMD_ACK_OK,
93 PRESTERA_CMD_ACK_FAILED,
94
95 PRESTERA_CMD_ACK_MAX
96 };
97
98 enum {
99 PRESTERA_PORT_TP_NA,
100 PRESTERA_PORT_TP_MDI,
101 PRESTERA_PORT_TP_MDIX,
102 PRESTERA_PORT_TP_AUTO,
103 };
104
105 enum {
106 PRESTERA_PORT_FLOOD_TYPE_UC = 0,
107 PRESTERA_PORT_FLOOD_TYPE_MC = 1,
108 };
109
110 enum {
111 PRESTERA_PORT_GOOD_OCTETS_RCV_CNT,
112 PRESTERA_PORT_BAD_OCTETS_RCV_CNT,
113 PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT,
114 PRESTERA_PORT_BRDC_PKTS_RCV_CNT,
115 PRESTERA_PORT_MC_PKTS_RCV_CNT,
116 PRESTERA_PORT_PKTS_64L_CNT,
117 PRESTERA_PORT_PKTS_65TO127L_CNT,
118 PRESTERA_PORT_PKTS_128TO255L_CNT,
119 PRESTERA_PORT_PKTS_256TO511L_CNT,
120 PRESTERA_PORT_PKTS_512TO1023L_CNT,
121 PRESTERA_PORT_PKTS_1024TOMAXL_CNT,
122 PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT,
123 PRESTERA_PORT_MC_PKTS_SENT_CNT,
124 PRESTERA_PORT_BRDC_PKTS_SENT_CNT,
125 PRESTERA_PORT_FC_SENT_CNT,
126 PRESTERA_PORT_GOOD_FC_RCV_CNT,
127 PRESTERA_PORT_DROP_EVENTS_CNT,
128 PRESTERA_PORT_UNDERSIZE_PKTS_CNT,
129 PRESTERA_PORT_FRAGMENTS_PKTS_CNT,
130 PRESTERA_PORT_OVERSIZE_PKTS_CNT,
131 PRESTERA_PORT_JABBER_PKTS_CNT,
132 PRESTERA_PORT_MAC_RCV_ERROR_CNT,
133 PRESTERA_PORT_BAD_CRC_CNT,
134 PRESTERA_PORT_COLLISIONS_CNT,
135 PRESTERA_PORT_LATE_COLLISIONS_CNT,
136 PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT,
137 PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT,
138 PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT,
139 PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT,
140 PRESTERA_PORT_GOOD_OCTETS_SENT_CNT,
141
142 PRESTERA_PORT_CNT_MAX
143 };
144
145 enum {
146 PRESTERA_FC_NONE,
147 PRESTERA_FC_SYMMETRIC,
148 PRESTERA_FC_ASYMMETRIC,
149 PRESTERA_FC_SYMM_ASYMM,
150 };
151
152 enum {
153 PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT = 0,
154 PRESTERA_HW_FDB_ENTRY_TYPE_LAG = 1,
155 PRESTERA_HW_FDB_ENTRY_TYPE_MAX = 2,
156 };
157
158 struct prestera_fw_event_handler {
159 struct list_head list;
160 struct rcu_head rcu;
161 enum prestera_event_type type;
162 prestera_event_cb_t func;
163 void *arg;
164 };
165
166 struct prestera_msg_cmd {
167 __le32 type;
168 };
169
170 struct prestera_msg_ret {
171 struct prestera_msg_cmd cmd;
172 __le32 status;
173 };
174
175 struct prestera_msg_common_req {
176 struct prestera_msg_cmd cmd;
177 };
178
179 struct prestera_msg_common_resp {
180 struct prestera_msg_ret ret;
181 };
182
183 struct prestera_msg_switch_attr_req {
184 struct prestera_msg_cmd cmd;
185 __le32 attr;
186 union {
187 __le32 ageing_timeout_ms;
188 struct {
189 u8 mac[ETH_ALEN];
190 u8 __pad[2];
191 };
192 } param;
193 };
194
195 struct prestera_msg_switch_init_resp {
196 struct prestera_msg_ret ret;
197 __le32 port_count;
198 __le32 mtu_max;
199 __le32 size_tbl_router_nexthop;
200 u8 switch_id;
201 u8 lag_max;
202 u8 lag_member_max;
203 };
204
205 struct prestera_msg_event_port_param {
206 union {
207 struct {
208 __le32 mode;
209 __le32 speed;
210 u8 oper;
211 u8 duplex;
212 u8 fc;
213 u8 fec;
214 } mac;
215 struct {
216 __le64 lmode_bmap;
217 u8 mdix;
218 u8 fc;
219 u8 __pad[2];
220 } __packed phy; /* make sure always 12 bytes size */
221 };
222 };
223
224 struct prestera_msg_port_cap_param {
225 __le64 link_mode;
226 u8 type;
227 u8 fec;
228 u8 fc;
229 u8 transceiver;
230 };
231
232 struct prestera_msg_port_flood_param {
233 u8 type;
234 u8 enable;
235 u8 __pad[2];
236 };
237
238 union prestera_msg_port_param {
239 __le32 mtu;
240 __le32 speed;
241 __le32 link_mode;
242 u8 admin_state;
243 u8 oper_state;
244 u8 mac[ETH_ALEN];
245 u8 accept_frm_type;
246 u8 learning;
247 u8 flood;
248 u8 type;
249 u8 duplex;
250 u8 fec;
251 u8 fc;
252 union {
253 struct {
254 u8 admin;
255 u8 fc;
256 u8 ap_enable;
257 u8 __reserved[5];
258 union {
259 struct {
260 __le32 mode;
261 __le32 speed;
262 u8 inband;
263 u8 duplex;
264 u8 fec;
265 u8 fec_supp;
266 } reg_mode;
267 struct {
268 __le32 mode;
269 __le32 speed;
270 u8 fec;
271 u8 fec_supp;
272 u8 __pad[2];
273 } ap_modes[PRESTERA_AP_PORT_MAX];
274 };
275 } mac;
276 struct {
277 __le64 modes;
278 __le32 mode;
279 u8 admin;
280 u8 adv_enable;
281 u8 mdix;
282 u8 __pad;
283 } phy;
284 } link;
285
286 struct prestera_msg_port_cap_param cap;
287 struct prestera_msg_port_flood_param flood_ext;
288 struct prestera_msg_event_port_param link_evt;
289 };
290
291 struct prestera_msg_port_attr_req {
292 struct prestera_msg_cmd cmd;
293 __le32 attr;
294 __le32 port;
295 __le32 dev;
296 union prestera_msg_port_param param;
297 };
298
299 struct prestera_msg_port_attr_resp {
300 struct prestera_msg_ret ret;
301 union prestera_msg_port_param param;
302 };
303
304 struct prestera_msg_port_stats_resp {
305 struct prestera_msg_ret ret;
306 __le64 stats[PRESTERA_PORT_CNT_MAX];
307 };
308
309 struct prestera_msg_port_info_req {
310 struct prestera_msg_cmd cmd;
311 __le32 port;
312 };
313
314 struct prestera_msg_port_info_resp {
315 struct prestera_msg_ret ret;
316 __le32 hw_id;
317 __le32 dev_id;
318 __le16 fp_id;
319 u8 pad[2];
320 };
321
322 struct prestera_msg_vlan_req {
323 struct prestera_msg_cmd cmd;
324 __le32 port;
325 __le32 dev;
326 __le16 vid;
327 u8 is_member;
328 u8 is_tagged;
329 };
330
331 struct prestera_msg_fdb_req {
332 struct prestera_msg_cmd cmd;
333 __le32 flush_mode;
334 union {
335 struct {
336 __le32 port;
337 __le32 dev;
338 };
339 __le16 lag_id;
340 } dest;
341 __le16 vid;
342 u8 dest_type;
343 u8 dynamic;
344 u8 mac[ETH_ALEN];
345 u8 __pad[2];
346 };
347
348 struct prestera_msg_bridge_req {
349 struct prestera_msg_cmd cmd;
350 __le32 port;
351 __le32 dev;
352 __le16 bridge;
353 u8 pad[2];
354 };
355
356 struct prestera_msg_bridge_resp {
357 struct prestera_msg_ret ret;
358 __le16 bridge;
359 u8 pad[2];
360 };
361
362 struct prestera_msg_acl_action {
363 __le32 id;
364 __le32 reserved[5];
365 };
366
367 struct prestera_msg_acl_match {
368 __le32 type;
369 __le32 __reserved;
370 union {
371 struct {
372 u8 key;
373 u8 mask;
374 } u8;
375 struct {
376 __le16 key;
377 __le16 mask;
378 } u16;
379 struct {
380 __le32 key;
381 __le32 mask;
382 } u32;
383 struct {
384 __le64 key;
385 __le64 mask;
386 } u64;
387 struct {
388 u8 key[ETH_ALEN];
389 u8 mask[ETH_ALEN];
390 } mac;
391 } keymask;
392 };
393
394 struct prestera_msg_acl_rule_req {
395 struct prestera_msg_cmd cmd;
396 __le32 id;
397 __le32 priority;
398 __le16 ruleset_id;
399 u8 n_actions;
400 u8 n_matches;
401 };
402
403 struct prestera_msg_acl_rule_resp {
404 struct prestera_msg_ret ret;
405 __le32 id;
406 };
407
408 struct prestera_msg_acl_rule_stats_resp {
409 struct prestera_msg_ret ret;
410 __le64 packets;
411 __le64 bytes;
412 };
413
414 struct prestera_msg_acl_ruleset_bind_req {
415 struct prestera_msg_cmd cmd;
416 __le32 port;
417 __le32 dev;
418 __le16 ruleset_id;
419 u8 pad[2];
420 };
421
422 struct prestera_msg_acl_ruleset_req {
423 struct prestera_msg_cmd cmd;
424 __le16 id;
425 u8 pad[2];
426 };
427
428 struct prestera_msg_acl_ruleset_resp {
429 struct prestera_msg_ret ret;
430 __le16 id;
431 u8 pad[2];
432 };
433
434 struct prestera_msg_span_req {
435 struct prestera_msg_cmd cmd;
436 __le32 port;
437 __le32 dev;
438 u8 id;
439 u8 pad[3];
440 };
441
442 struct prestera_msg_span_resp {
443 struct prestera_msg_ret ret;
444 u8 id;
445 u8 pad[3];
446 };
447
448 struct prestera_msg_stp_req {
449 struct prestera_msg_cmd cmd;
450 __le32 port;
451 __le32 dev;
452 __le16 vid;
453 u8 state;
454 u8 __pad;
455 };
456
457 struct prestera_msg_rxtx_req {
458 struct prestera_msg_cmd cmd;
459 u8 use_sdma;
460 u8 pad[3];
461 };
462
463 struct prestera_msg_rxtx_resp {
464 struct prestera_msg_ret ret;
465 __le32 map_addr;
466 };
467
468 struct prestera_msg_lag_req {
469 struct prestera_msg_cmd cmd;
470 __le32 port;
471 __le32 dev;
472 __le16 lag_id;
473 u8 pad[2];
474 };
475
476 struct prestera_msg_cpu_code_counter_req {
477 struct prestera_msg_cmd cmd;
478 u8 counter_type;
479 u8 code;
480 u8 pad[2];
481 };
482
483 struct mvsw_msg_cpu_code_counter_ret {
484 struct prestera_msg_ret ret;
485 __le64 packet_count;
486 };
487
488 struct prestera_msg_event {
489 __le16 type;
490 __le16 id;
491 };
492
493 struct prestera_msg_event_port {
494 struct prestera_msg_event id;
495 __le32 port_id;
496 struct prestera_msg_event_port_param param;
497 };
498
499 union prestera_msg_event_fdb_param {
500 u8 mac[ETH_ALEN];
501 };
502
503 struct prestera_msg_event_fdb {
504 struct prestera_msg_event id;
505 __le32 vid;
506 union {
507 __le32 port_id;
508 __le16 lag_id;
509 } dest;
510 union prestera_msg_event_fdb_param param;
511 u8 dest_type;
512 };
513
prestera_hw_build_tests(void)514 static void prestera_hw_build_tests(void)
515 {
516 /* check requests */
517 BUILD_BUG_ON(sizeof(struct prestera_msg_common_req) != 4);
518 BUILD_BUG_ON(sizeof(struct prestera_msg_switch_attr_req) != 16);
519 BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_req) != 144);
520 BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_req) != 8);
521 BUILD_BUG_ON(sizeof(struct prestera_msg_vlan_req) != 16);
522 BUILD_BUG_ON(sizeof(struct prestera_msg_fdb_req) != 28);
523 BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_req) != 16);
524 BUILD_BUG_ON(sizeof(struct prestera_msg_acl_rule_req) != 16);
525 BUILD_BUG_ON(sizeof(struct prestera_msg_acl_ruleset_bind_req) != 16);
526 BUILD_BUG_ON(sizeof(struct prestera_msg_acl_ruleset_req) != 8);
527 BUILD_BUG_ON(sizeof(struct prestera_msg_span_req) != 16);
528 BUILD_BUG_ON(sizeof(struct prestera_msg_stp_req) != 16);
529 BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_req) != 8);
530 BUILD_BUG_ON(sizeof(struct prestera_msg_lag_req) != 16);
531 BUILD_BUG_ON(sizeof(struct prestera_msg_cpu_code_counter_req) != 8);
532
533 /* check responses */
534 BUILD_BUG_ON(sizeof(struct prestera_msg_common_resp) != 8);
535 BUILD_BUG_ON(sizeof(struct prestera_msg_switch_init_resp) != 24);
536 BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_resp) != 136);
537 BUILD_BUG_ON(sizeof(struct prestera_msg_port_stats_resp) != 248);
538 BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_resp) != 20);
539 BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_resp) != 12);
540 BUILD_BUG_ON(sizeof(struct prestera_msg_acl_rule_resp) != 12);
541 BUILD_BUG_ON(sizeof(struct prestera_msg_acl_rule_stats_resp) != 24);
542 BUILD_BUG_ON(sizeof(struct prestera_msg_acl_ruleset_resp) != 12);
543 BUILD_BUG_ON(sizeof(struct prestera_msg_span_resp) != 12);
544 BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_resp) != 12);
545
546 /* check events */
547 BUILD_BUG_ON(sizeof(struct prestera_msg_event_port) != 20);
548 BUILD_BUG_ON(sizeof(struct prestera_msg_event_fdb) != 20);
549 }
550
551 static u8 prestera_hw_mdix_to_eth(u8 mode);
552 static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause);
553
__prestera_cmd_ret(struct prestera_switch * sw,enum prestera_cmd_type_t type,struct prestera_msg_cmd * cmd,size_t clen,struct prestera_msg_ret * ret,size_t rlen,int waitms)554 static int __prestera_cmd_ret(struct prestera_switch *sw,
555 enum prestera_cmd_type_t type,
556 struct prestera_msg_cmd *cmd, size_t clen,
557 struct prestera_msg_ret *ret, size_t rlen,
558 int waitms)
559 {
560 struct prestera_device *dev = sw->dev;
561 int err;
562
563 cmd->type = __cpu_to_le32(type);
564
565 err = dev->send_req(dev, 0, cmd, clen, ret, rlen, waitms);
566 if (err)
567 return err;
568
569 if (ret->cmd.type != __cpu_to_le32(PRESTERA_CMD_TYPE_ACK))
570 return -EBADE;
571 if (ret->status != __cpu_to_le32(PRESTERA_CMD_ACK_OK))
572 return -EINVAL;
573
574 return 0;
575 }
576
prestera_cmd_ret(struct prestera_switch * sw,enum prestera_cmd_type_t type,struct prestera_msg_cmd * cmd,size_t clen,struct prestera_msg_ret * ret,size_t rlen)577 static int prestera_cmd_ret(struct prestera_switch *sw,
578 enum prestera_cmd_type_t type,
579 struct prestera_msg_cmd *cmd, size_t clen,
580 struct prestera_msg_ret *ret, size_t rlen)
581 {
582 return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0);
583 }
584
prestera_cmd_ret_wait(struct prestera_switch * sw,enum prestera_cmd_type_t type,struct prestera_msg_cmd * cmd,size_t clen,struct prestera_msg_ret * ret,size_t rlen,int waitms)585 static int prestera_cmd_ret_wait(struct prestera_switch *sw,
586 enum prestera_cmd_type_t type,
587 struct prestera_msg_cmd *cmd, size_t clen,
588 struct prestera_msg_ret *ret, size_t rlen,
589 int waitms)
590 {
591 return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms);
592 }
593
prestera_cmd(struct prestera_switch * sw,enum prestera_cmd_type_t type,struct prestera_msg_cmd * cmd,size_t clen)594 static int prestera_cmd(struct prestera_switch *sw,
595 enum prestera_cmd_type_t type,
596 struct prestera_msg_cmd *cmd, size_t clen)
597 {
598 struct prestera_msg_common_resp resp;
599
600 return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp));
601 }
602
prestera_fw_parse_port_evt(void * msg,struct prestera_event * evt)603 static int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt)
604 {
605 struct prestera_msg_event_port *hw_evt;
606
607 hw_evt = (struct prestera_msg_event_port *)msg;
608
609 evt->port_evt.port_id = __le32_to_cpu(hw_evt->port_id);
610
611 if (evt->id == PRESTERA_PORT_EVENT_MAC_STATE_CHANGED) {
612 evt->port_evt.data.mac.oper = hw_evt->param.mac.oper;
613 evt->port_evt.data.mac.mode =
614 __le32_to_cpu(hw_evt->param.mac.mode);
615 evt->port_evt.data.mac.speed =
616 __le32_to_cpu(hw_evt->param.mac.speed);
617 evt->port_evt.data.mac.duplex = hw_evt->param.mac.duplex;
618 evt->port_evt.data.mac.fc = hw_evt->param.mac.fc;
619 evt->port_evt.data.mac.fec = hw_evt->param.mac.fec;
620 } else {
621 return -EINVAL;
622 }
623
624 return 0;
625 }
626
prestera_fw_parse_fdb_evt(void * msg,struct prestera_event * evt)627 static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt)
628 {
629 struct prestera_msg_event_fdb *hw_evt = msg;
630
631 switch (hw_evt->dest_type) {
632 case PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT:
633 evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_REG_PORT;
634 evt->fdb_evt.dest.port_id = __le32_to_cpu(hw_evt->dest.port_id);
635 break;
636 case PRESTERA_HW_FDB_ENTRY_TYPE_LAG:
637 evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_LAG;
638 evt->fdb_evt.dest.lag_id = __le16_to_cpu(hw_evt->dest.lag_id);
639 break;
640 default:
641 return -EINVAL;
642 }
643
644 evt->fdb_evt.vid = __le32_to_cpu(hw_evt->vid);
645
646 ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac);
647
648 return 0;
649 }
650
651 static struct prestera_fw_evt_parser {
652 int (*func)(void *msg, struct prestera_event *evt);
653 } fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = {
654 [PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt },
655 [PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt },
656 };
657
658 static struct prestera_fw_event_handler *
__find_event_handler(const struct prestera_switch * sw,enum prestera_event_type type)659 __find_event_handler(const struct prestera_switch *sw,
660 enum prestera_event_type type)
661 {
662 struct prestera_fw_event_handler *eh;
663
664 list_for_each_entry_rcu(eh, &sw->event_handlers, list) {
665 if (eh->type == type)
666 return eh;
667 }
668
669 return NULL;
670 }
671
prestera_find_event_handler(const struct prestera_switch * sw,enum prestera_event_type type,struct prestera_fw_event_handler * eh)672 static int prestera_find_event_handler(const struct prestera_switch *sw,
673 enum prestera_event_type type,
674 struct prestera_fw_event_handler *eh)
675 {
676 struct prestera_fw_event_handler *tmp;
677 int err = 0;
678
679 rcu_read_lock();
680 tmp = __find_event_handler(sw, type);
681 if (tmp)
682 *eh = *tmp;
683 else
684 err = -ENOENT;
685 rcu_read_unlock();
686
687 return err;
688 }
689
prestera_evt_recv(struct prestera_device * dev,void * buf,size_t size)690 static int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size)
691 {
692 struct prestera_switch *sw = dev->priv;
693 struct prestera_msg_event *msg = buf;
694 struct prestera_fw_event_handler eh;
695 struct prestera_event evt;
696 u16 msg_type;
697 int err;
698
699 msg_type = __le16_to_cpu(msg->type);
700 if (msg_type >= PRESTERA_EVENT_TYPE_MAX)
701 return -EINVAL;
702 if (!fw_event_parsers[msg_type].func)
703 return -ENOENT;
704
705 err = prestera_find_event_handler(sw, msg_type, &eh);
706 if (err)
707 return err;
708
709 evt.id = __le16_to_cpu(msg->id);
710
711 err = fw_event_parsers[msg_type].func(buf, &evt);
712 if (err)
713 return err;
714
715 eh.func(sw, &evt, eh.arg);
716
717 return 0;
718 }
719
prestera_pkt_recv(struct prestera_device * dev)720 static void prestera_pkt_recv(struct prestera_device *dev)
721 {
722 struct prestera_switch *sw = dev->priv;
723 struct prestera_fw_event_handler eh;
724 struct prestera_event ev;
725 int err;
726
727 ev.id = PRESTERA_RXTX_EVENT_RCV_PKT;
728
729 err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh);
730 if (err)
731 return;
732
733 eh.func(sw, &ev, eh.arg);
734 }
735
prestera_hw_mdix_to_eth(u8 mode)736 static u8 prestera_hw_mdix_to_eth(u8 mode)
737 {
738 switch (mode) {
739 case PRESTERA_PORT_TP_MDI:
740 return ETH_TP_MDI;
741 case PRESTERA_PORT_TP_MDIX:
742 return ETH_TP_MDI_X;
743 case PRESTERA_PORT_TP_AUTO:
744 return ETH_TP_MDI_AUTO;
745 default:
746 return ETH_TP_MDI_INVALID;
747 }
748 }
749
prestera_hw_mdix_from_eth(u8 mode)750 static u8 prestera_hw_mdix_from_eth(u8 mode)
751 {
752 switch (mode) {
753 case ETH_TP_MDI:
754 return PRESTERA_PORT_TP_MDI;
755 case ETH_TP_MDI_X:
756 return PRESTERA_PORT_TP_MDIX;
757 case ETH_TP_MDI_AUTO:
758 return PRESTERA_PORT_TP_AUTO;
759 default:
760 return PRESTERA_PORT_TP_NA;
761 }
762 }
763
prestera_hw_port_info_get(const struct prestera_port * port,u32 * dev_id,u32 * hw_id,u16 * fp_id)764 int prestera_hw_port_info_get(const struct prestera_port *port,
765 u32 *dev_id, u32 *hw_id, u16 *fp_id)
766 {
767 struct prestera_msg_port_info_req req = {
768 .port = __cpu_to_le32(port->id),
769 };
770 struct prestera_msg_port_info_resp resp;
771 int err;
772
773 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET,
774 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
775 if (err)
776 return err;
777
778 *dev_id = __le32_to_cpu(resp.dev_id);
779 *hw_id = __le32_to_cpu(resp.hw_id);
780 *fp_id = __le16_to_cpu(resp.fp_id);
781
782 return 0;
783 }
784
prestera_hw_switch_mac_set(struct prestera_switch * sw,const char * mac)785 int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac)
786 {
787 struct prestera_msg_switch_attr_req req = {
788 .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_MAC),
789 };
790
791 ether_addr_copy(req.param.mac, mac);
792
793 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
794 &req.cmd, sizeof(req));
795 }
796
prestera_hw_switch_init(struct prestera_switch * sw)797 int prestera_hw_switch_init(struct prestera_switch *sw)
798 {
799 struct prestera_msg_switch_init_resp resp;
800 struct prestera_msg_common_req req;
801 int err;
802
803 INIT_LIST_HEAD(&sw->event_handlers);
804
805 prestera_hw_build_tests();
806
807 err = prestera_cmd_ret_wait(sw, PRESTERA_CMD_TYPE_SWITCH_INIT,
808 &req.cmd, sizeof(req),
809 &resp.ret, sizeof(resp),
810 PRESTERA_SWITCH_INIT_TIMEOUT_MS);
811 if (err)
812 return err;
813
814 sw->dev->recv_msg = prestera_evt_recv;
815 sw->dev->recv_pkt = prestera_pkt_recv;
816 sw->port_count = __le32_to_cpu(resp.port_count);
817 sw->mtu_min = PRESTERA_MIN_MTU;
818 sw->mtu_max = __le32_to_cpu(resp.mtu_max);
819 sw->id = resp.switch_id;
820 sw->lag_member_max = resp.lag_member_max;
821 sw->lag_max = resp.lag_max;
822
823 return 0;
824 }
825
prestera_hw_switch_fini(struct prestera_switch * sw)826 void prestera_hw_switch_fini(struct prestera_switch *sw)
827 {
828 WARN_ON(!list_empty(&sw->event_handlers));
829 }
830
prestera_hw_switch_ageing_set(struct prestera_switch * sw,u32 ageing_ms)831 int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms)
832 {
833 struct prestera_msg_switch_attr_req req = {
834 .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_AGEING),
835 .param = {
836 .ageing_timeout_ms = __cpu_to_le32(ageing_ms),
837 },
838 };
839
840 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
841 &req.cmd, sizeof(req));
842 }
843
prestera_hw_port_mac_mode_get(const struct prestera_port * port,u32 * mode,u32 * speed,u8 * duplex,u8 * fec)844 int prestera_hw_port_mac_mode_get(const struct prestera_port *port,
845 u32 *mode, u32 *speed, u8 *duplex, u8 *fec)
846 {
847 struct prestera_msg_port_attr_resp resp;
848 struct prestera_msg_port_attr_req req = {
849 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
850 .port = __cpu_to_le32(port->hw_id),
851 .dev = __cpu_to_le32(port->dev_id)
852 };
853 int err;
854
855 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
856 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
857 if (err)
858 return err;
859
860 if (mode)
861 *mode = __le32_to_cpu(resp.param.link_evt.mac.mode);
862
863 if (speed)
864 *speed = __le32_to_cpu(resp.param.link_evt.mac.speed);
865
866 if (duplex)
867 *duplex = resp.param.link_evt.mac.duplex;
868
869 if (fec)
870 *fec = resp.param.link_evt.mac.fec;
871
872 return err;
873 }
874
prestera_hw_port_mac_mode_set(const struct prestera_port * port,bool admin,u32 mode,u8 inband,u32 speed,u8 duplex,u8 fec)875 int prestera_hw_port_mac_mode_set(const struct prestera_port *port,
876 bool admin, u32 mode, u8 inband,
877 u32 speed, u8 duplex, u8 fec)
878 {
879 struct prestera_msg_port_attr_req req = {
880 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
881 .port = __cpu_to_le32(port->hw_id),
882 .dev = __cpu_to_le32(port->dev_id),
883 .param = {
884 .link = {
885 .mac = {
886 .admin = admin,
887 .reg_mode.mode = __cpu_to_le32(mode),
888 .reg_mode.inband = inband,
889 .reg_mode.speed = __cpu_to_le32(speed),
890 .reg_mode.duplex = duplex,
891 .reg_mode.fec = fec
892 }
893 }
894 }
895 };
896
897 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
898 &req.cmd, sizeof(req));
899 }
900
prestera_hw_port_phy_mode_get(const struct prestera_port * port,u8 * mdix,u64 * lmode_bmap,bool * fc_pause,bool * fc_asym)901 int prestera_hw_port_phy_mode_get(const struct prestera_port *port,
902 u8 *mdix, u64 *lmode_bmap,
903 bool *fc_pause, bool *fc_asym)
904 {
905 struct prestera_msg_port_attr_resp resp;
906 struct prestera_msg_port_attr_req req = {
907 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_MODE),
908 .port = __cpu_to_le32(port->hw_id),
909 .dev = __cpu_to_le32(port->dev_id)
910 };
911 int err;
912
913 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
914 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
915 if (err)
916 return err;
917
918 if (mdix)
919 *mdix = prestera_hw_mdix_to_eth(resp.param.link_evt.phy.mdix);
920
921 if (lmode_bmap)
922 *lmode_bmap = __le64_to_cpu(resp.param.link_evt.phy.lmode_bmap);
923
924 if (fc_pause && fc_asym)
925 prestera_hw_remote_fc_to_eth(resp.param.link_evt.phy.fc,
926 fc_pause, fc_asym);
927
928 return err;
929 }
930
prestera_hw_port_phy_mode_set(const struct prestera_port * port,bool admin,bool adv,u32 mode,u64 modes,u8 mdix)931 int prestera_hw_port_phy_mode_set(const struct prestera_port *port,
932 bool admin, bool adv, u32 mode, u64 modes,
933 u8 mdix)
934 {
935 struct prestera_msg_port_attr_req req = {
936 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_MODE),
937 .port = __cpu_to_le32(port->hw_id),
938 .dev = __cpu_to_le32(port->dev_id),
939 .param = {
940 .link = {
941 .phy = {
942 .admin = admin,
943 .adv_enable = adv ? 1 : 0,
944 .mode = __cpu_to_le32(mode),
945 .modes = __cpu_to_le64(modes),
946 }
947 }
948 }
949 };
950
951 req.param.link.phy.mdix = prestera_hw_mdix_from_eth(mdix);
952
953 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
954 &req.cmd, sizeof(req));
955 }
956
prestera_hw_port_mtu_set(const struct prestera_port * port,u32 mtu)957 int prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu)
958 {
959 struct prestera_msg_port_attr_req req = {
960 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MTU),
961 .port = __cpu_to_le32(port->hw_id),
962 .dev = __cpu_to_le32(port->dev_id),
963 .param = {
964 .mtu = __cpu_to_le32(mtu),
965 }
966 };
967
968 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
969 &req.cmd, sizeof(req));
970 }
971
prestera_hw_port_mac_set(const struct prestera_port * port,const char * mac)972 int prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac)
973 {
974 struct prestera_msg_port_attr_req req = {
975 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC),
976 .port = __cpu_to_le32(port->hw_id),
977 .dev = __cpu_to_le32(port->dev_id),
978 };
979
980 ether_addr_copy(req.param.mac, mac);
981
982 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
983 &req.cmd, sizeof(req));
984 }
985
prestera_hw_port_accept_frm_type(struct prestera_port * port,enum prestera_accept_frm_type type)986 int prestera_hw_port_accept_frm_type(struct prestera_port *port,
987 enum prestera_accept_frm_type type)
988 {
989 struct prestera_msg_port_attr_req req = {
990 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE),
991 .port = __cpu_to_le32(port->hw_id),
992 .dev = __cpu_to_le32(port->dev_id),
993 .param = {
994 .accept_frm_type = type,
995 }
996 };
997
998 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
999 &req.cmd, sizeof(req));
1000 }
1001
prestera_hw_port_cap_get(const struct prestera_port * port,struct prestera_port_caps * caps)1002 int prestera_hw_port_cap_get(const struct prestera_port *port,
1003 struct prestera_port_caps *caps)
1004 {
1005 struct prestera_msg_port_attr_req req = {
1006 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_CAPABILITY),
1007 .port = __cpu_to_le32(port->hw_id),
1008 .dev = __cpu_to_le32(port->dev_id),
1009 };
1010 struct prestera_msg_port_attr_resp resp;
1011 int err;
1012
1013 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1014 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1015 if (err)
1016 return err;
1017
1018 caps->supp_link_modes = __le64_to_cpu(resp.param.cap.link_mode);
1019 caps->transceiver = resp.param.cap.transceiver;
1020 caps->supp_fec = resp.param.cap.fec;
1021 caps->type = resp.param.cap.type;
1022
1023 return err;
1024 }
1025
prestera_hw_remote_fc_to_eth(u8 fc,bool * pause,bool * asym_pause)1026 static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause)
1027 {
1028 switch (fc) {
1029 case PRESTERA_FC_SYMMETRIC:
1030 *pause = true;
1031 *asym_pause = false;
1032 break;
1033 case PRESTERA_FC_ASYMMETRIC:
1034 *pause = false;
1035 *asym_pause = true;
1036 break;
1037 case PRESTERA_FC_SYMM_ASYMM:
1038 *pause = true;
1039 *asym_pause = true;
1040 break;
1041 default:
1042 *pause = false;
1043 *asym_pause = false;
1044 }
1045 }
1046
prestera_hw_acl_ruleset_create(struct prestera_switch * sw,u16 * ruleset_id)1047 int prestera_hw_acl_ruleset_create(struct prestera_switch *sw, u16 *ruleset_id)
1048 {
1049 struct prestera_msg_acl_ruleset_resp resp;
1050 struct prestera_msg_acl_ruleset_req req;
1051 int err;
1052
1053 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ACL_RULESET_CREATE,
1054 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1055 if (err)
1056 return err;
1057
1058 *ruleset_id = __le16_to_cpu(resp.id);
1059
1060 return 0;
1061 }
1062
prestera_hw_acl_ruleset_del(struct prestera_switch * sw,u16 ruleset_id)1063 int prestera_hw_acl_ruleset_del(struct prestera_switch *sw, u16 ruleset_id)
1064 {
1065 struct prestera_msg_acl_ruleset_req req = {
1066 .id = __cpu_to_le16(ruleset_id),
1067 };
1068
1069 return prestera_cmd(sw, PRESTERA_CMD_TYPE_ACL_RULESET_DELETE,
1070 &req.cmd, sizeof(req));
1071 }
1072
prestera_hw_acl_actions_put(struct prestera_msg_acl_action * action,struct prestera_acl_rule * rule)1073 static int prestera_hw_acl_actions_put(struct prestera_msg_acl_action *action,
1074 struct prestera_acl_rule *rule)
1075 {
1076 struct list_head *a_list = prestera_acl_rule_action_list_get(rule);
1077 struct prestera_acl_rule_action_entry *a_entry;
1078 int i = 0;
1079
1080 list_for_each_entry(a_entry, a_list, list) {
1081 action[i].id = __cpu_to_le32(a_entry->id);
1082
1083 switch (a_entry->id) {
1084 case PRESTERA_ACL_RULE_ACTION_ACCEPT:
1085 case PRESTERA_ACL_RULE_ACTION_DROP:
1086 case PRESTERA_ACL_RULE_ACTION_TRAP:
1087 /* just rule action id, no specific data */
1088 break;
1089 default:
1090 return -EINVAL;
1091 }
1092
1093 i++;
1094 }
1095
1096 return 0;
1097 }
1098
prestera_hw_acl_matches_put(struct prestera_msg_acl_match * match,struct prestera_acl_rule * rule)1099 static int prestera_hw_acl_matches_put(struct prestera_msg_acl_match *match,
1100 struct prestera_acl_rule *rule)
1101 {
1102 struct list_head *m_list = prestera_acl_rule_match_list_get(rule);
1103 struct prestera_acl_rule_match_entry *m_entry;
1104 int i = 0;
1105
1106 list_for_each_entry(m_entry, m_list, list) {
1107 match[i].type = __cpu_to_le32(m_entry->type);
1108
1109 switch (m_entry->type) {
1110 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_ETH_TYPE:
1111 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_L4_PORT_SRC:
1112 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_L4_PORT_DST:
1113 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_VLAN_ID:
1114 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_VLAN_TPID:
1115 match[i].keymask.u16.key =
1116 __cpu_to_le16(m_entry->keymask.u16.key);
1117 match[i].keymask.u16.mask =
1118 __cpu_to_le16(m_entry->keymask.u16.mask);
1119 break;
1120 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_ICMP_TYPE:
1121 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_ICMP_CODE:
1122 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_IP_PROTO:
1123 match[i].keymask.u8.key = m_entry->keymask.u8.key;
1124 match[i].keymask.u8.mask = m_entry->keymask.u8.mask;
1125 break;
1126 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_ETH_SMAC:
1127 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_ETH_DMAC:
1128 memcpy(match[i].keymask.mac.key,
1129 m_entry->keymask.mac.key,
1130 sizeof(match[i].keymask.mac.key));
1131 memcpy(match[i].keymask.mac.mask,
1132 m_entry->keymask.mac.mask,
1133 sizeof(match[i].keymask.mac.mask));
1134 break;
1135 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_IP_SRC:
1136 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_IP_DST:
1137 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_L4_PORT_RANGE_SRC:
1138 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_L4_PORT_RANGE_DST:
1139 match[i].keymask.u32.key =
1140 __cpu_to_le32(m_entry->keymask.u32.key);
1141 match[i].keymask.u32.mask =
1142 __cpu_to_le32(m_entry->keymask.u32.mask);
1143 break;
1144 case PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_PORT:
1145 match[i].keymask.u64.key =
1146 __cpu_to_le64(m_entry->keymask.u64.key);
1147 match[i].keymask.u64.mask =
1148 __cpu_to_le64(m_entry->keymask.u64.mask);
1149 break;
1150 default:
1151 return -EINVAL;
1152 }
1153
1154 i++;
1155 }
1156
1157 return 0;
1158 }
1159
prestera_hw_acl_rule_add(struct prestera_switch * sw,struct prestera_acl_rule * rule,u32 * rule_id)1160 int prestera_hw_acl_rule_add(struct prestera_switch *sw,
1161 struct prestera_acl_rule *rule,
1162 u32 *rule_id)
1163 {
1164 struct prestera_msg_acl_action *actions;
1165 struct prestera_msg_acl_match *matches;
1166 struct prestera_msg_acl_rule_resp resp;
1167 struct prestera_msg_acl_rule_req *req;
1168 u8 n_actions;
1169 u8 n_matches;
1170 void *buff;
1171 u32 size;
1172 int err;
1173
1174 n_actions = prestera_acl_rule_action_len(rule);
1175 n_matches = prestera_acl_rule_match_len(rule);
1176
1177 size = sizeof(*req) + sizeof(*actions) * n_actions +
1178 sizeof(*matches) * n_matches;
1179
1180 buff = kzalloc(size, GFP_KERNEL);
1181 if (!buff)
1182 return -ENOMEM;
1183
1184 req = buff;
1185 actions = buff + sizeof(*req);
1186 matches = buff + sizeof(*req) + sizeof(*actions) * n_actions;
1187
1188 /* put acl actions into the message */
1189 err = prestera_hw_acl_actions_put(actions, rule);
1190 if (err)
1191 goto free_buff;
1192
1193 /* put acl matches into the message */
1194 err = prestera_hw_acl_matches_put(matches, rule);
1195 if (err)
1196 goto free_buff;
1197
1198 req->ruleset_id = __cpu_to_le16(prestera_acl_rule_ruleset_id_get(rule));
1199 req->priority = __cpu_to_le32(prestera_acl_rule_priority_get(rule));
1200 req->n_actions = prestera_acl_rule_action_len(rule);
1201 req->n_matches = prestera_acl_rule_match_len(rule);
1202
1203 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ACL_RULE_ADD,
1204 &req->cmd, size, &resp.ret, sizeof(resp));
1205 if (err)
1206 goto free_buff;
1207
1208 *rule_id = __le32_to_cpu(resp.id);
1209 free_buff:
1210 kfree(buff);
1211 return err;
1212 }
1213
prestera_hw_acl_rule_del(struct prestera_switch * sw,u32 rule_id)1214 int prestera_hw_acl_rule_del(struct prestera_switch *sw, u32 rule_id)
1215 {
1216 struct prestera_msg_acl_rule_req req = {
1217 .id = __cpu_to_le32(rule_id)
1218 };
1219
1220 return prestera_cmd(sw, PRESTERA_CMD_TYPE_ACL_RULE_DELETE,
1221 &req.cmd, sizeof(req));
1222 }
1223
prestera_hw_acl_rule_stats_get(struct prestera_switch * sw,u32 rule_id,u64 * packets,u64 * bytes)1224 int prestera_hw_acl_rule_stats_get(struct prestera_switch *sw, u32 rule_id,
1225 u64 *packets, u64 *bytes)
1226 {
1227 struct prestera_msg_acl_rule_stats_resp resp;
1228 struct prestera_msg_acl_rule_req req = {
1229 .id = __cpu_to_le32(rule_id)
1230 };
1231 int err;
1232
1233 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ACL_RULE_STATS_GET,
1234 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1235 if (err)
1236 return err;
1237
1238 *packets = __le64_to_cpu(resp.packets);
1239 *bytes = __le64_to_cpu(resp.bytes);
1240
1241 return 0;
1242 }
1243
prestera_hw_acl_port_bind(const struct prestera_port * port,u16 ruleset_id)1244 int prestera_hw_acl_port_bind(const struct prestera_port *port, u16 ruleset_id)
1245 {
1246 struct prestera_msg_acl_ruleset_bind_req req = {
1247 .port = __cpu_to_le32(port->hw_id),
1248 .dev = __cpu_to_le32(port->dev_id),
1249 .ruleset_id = __cpu_to_le16(ruleset_id),
1250 };
1251
1252 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_ACL_PORT_BIND,
1253 &req.cmd, sizeof(req));
1254 }
1255
prestera_hw_acl_port_unbind(const struct prestera_port * port,u16 ruleset_id)1256 int prestera_hw_acl_port_unbind(const struct prestera_port *port,
1257 u16 ruleset_id)
1258 {
1259 struct prestera_msg_acl_ruleset_bind_req req = {
1260 .port = __cpu_to_le32(port->hw_id),
1261 .dev = __cpu_to_le32(port->dev_id),
1262 .ruleset_id = __cpu_to_le16(ruleset_id),
1263 };
1264
1265 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_ACL_PORT_UNBIND,
1266 &req.cmd, sizeof(req));
1267 }
1268
prestera_hw_span_get(const struct prestera_port * port,u8 * span_id)1269 int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id)
1270 {
1271 struct prestera_msg_span_resp resp;
1272 struct prestera_msg_span_req req = {
1273 .port = __cpu_to_le32(port->hw_id),
1274 .dev = __cpu_to_le32(port->dev_id),
1275 };
1276 int err;
1277
1278 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_SPAN_GET,
1279 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1280 if (err)
1281 return err;
1282
1283 *span_id = resp.id;
1284
1285 return 0;
1286 }
1287
prestera_hw_span_bind(const struct prestera_port * port,u8 span_id)1288 int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id)
1289 {
1290 struct prestera_msg_span_req req = {
1291 .port = __cpu_to_le32(port->hw_id),
1292 .dev = __cpu_to_le32(port->dev_id),
1293 .id = span_id,
1294 };
1295
1296 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_BIND,
1297 &req.cmd, sizeof(req));
1298 }
1299
prestera_hw_span_unbind(const struct prestera_port * port)1300 int prestera_hw_span_unbind(const struct prestera_port *port)
1301 {
1302 struct prestera_msg_span_req req = {
1303 .port = __cpu_to_le32(port->hw_id),
1304 .dev = __cpu_to_le32(port->dev_id),
1305 };
1306
1307 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_UNBIND,
1308 &req.cmd, sizeof(req));
1309 }
1310
prestera_hw_span_release(struct prestera_switch * sw,u8 span_id)1311 int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id)
1312 {
1313 struct prestera_msg_span_req req = {
1314 .id = span_id
1315 };
1316
1317 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SPAN_RELEASE,
1318 &req.cmd, sizeof(req));
1319 }
1320
prestera_hw_port_type_get(const struct prestera_port * port,u8 * type)1321 int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
1322 {
1323 struct prestera_msg_port_attr_req req = {
1324 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_TYPE),
1325 .port = __cpu_to_le32(port->hw_id),
1326 .dev = __cpu_to_le32(port->dev_id),
1327 };
1328 struct prestera_msg_port_attr_resp resp;
1329 int err;
1330
1331 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1332 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1333 if (err)
1334 return err;
1335
1336 *type = resp.param.type;
1337
1338 return 0;
1339 }
1340
prestera_hw_port_speed_get(const struct prestera_port * port,u32 * speed)1341 int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed)
1342 {
1343 struct prestera_msg_port_attr_req req = {
1344 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_SPEED),
1345 .port = __cpu_to_le32(port->hw_id),
1346 .dev = __cpu_to_le32(port->dev_id),
1347 };
1348 struct prestera_msg_port_attr_resp resp;
1349 int err;
1350
1351 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1352 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1353 if (err)
1354 return err;
1355
1356 *speed = __le32_to_cpu(resp.param.speed);
1357
1358 return 0;
1359 }
1360
prestera_hw_port_autoneg_restart(struct prestera_port * port)1361 int prestera_hw_port_autoneg_restart(struct prestera_port *port)
1362 {
1363 struct prestera_msg_port_attr_req req = {
1364 .attr =
1365 __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART),
1366 .port = __cpu_to_le32(port->hw_id),
1367 .dev = __cpu_to_le32(port->dev_id),
1368 };
1369
1370 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1371 &req.cmd, sizeof(req));
1372 }
1373
prestera_hw_port_stats_get(const struct prestera_port * port,struct prestera_port_stats * st)1374 int prestera_hw_port_stats_get(const struct prestera_port *port,
1375 struct prestera_port_stats *st)
1376 {
1377 struct prestera_msg_port_attr_req req = {
1378 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_STATS),
1379 .port = __cpu_to_le32(port->hw_id),
1380 .dev = __cpu_to_le32(port->dev_id),
1381 };
1382 struct prestera_msg_port_stats_resp resp;
1383 __le64 *hw = resp.stats;
1384 int err;
1385
1386 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1387 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1388 if (err)
1389 return err;
1390
1391 st->good_octets_received =
1392 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_RCV_CNT]);
1393 st->bad_octets_received =
1394 __le64_to_cpu(hw[PRESTERA_PORT_BAD_OCTETS_RCV_CNT]);
1395 st->mac_trans_error =
1396 __le64_to_cpu(hw[PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT]);
1397 st->broadcast_frames_received =
1398 __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_RCV_CNT]);
1399 st->multicast_frames_received =
1400 __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_RCV_CNT]);
1401 st->frames_64_octets = __le64_to_cpu(hw[PRESTERA_PORT_PKTS_64L_CNT]);
1402 st->frames_65_to_127_octets =
1403 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_65TO127L_CNT]);
1404 st->frames_128_to_255_octets =
1405 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_128TO255L_CNT]);
1406 st->frames_256_to_511_octets =
1407 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_256TO511L_CNT]);
1408 st->frames_512_to_1023_octets =
1409 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_512TO1023L_CNT]);
1410 st->frames_1024_to_max_octets =
1411 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_1024TOMAXL_CNT]);
1412 st->excessive_collision =
1413 __le64_to_cpu(hw[PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT]);
1414 st->multicast_frames_sent =
1415 __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_SENT_CNT]);
1416 st->broadcast_frames_sent =
1417 __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_SENT_CNT]);
1418 st->fc_sent = __le64_to_cpu(hw[PRESTERA_PORT_FC_SENT_CNT]);
1419 st->fc_received = __le64_to_cpu(hw[PRESTERA_PORT_GOOD_FC_RCV_CNT]);
1420 st->buffer_overrun = __le64_to_cpu(hw[PRESTERA_PORT_DROP_EVENTS_CNT]);
1421 st->undersize = __le64_to_cpu(hw[PRESTERA_PORT_UNDERSIZE_PKTS_CNT]);
1422 st->fragments = __le64_to_cpu(hw[PRESTERA_PORT_FRAGMENTS_PKTS_CNT]);
1423 st->oversize = __le64_to_cpu(hw[PRESTERA_PORT_OVERSIZE_PKTS_CNT]);
1424 st->jabber = __le64_to_cpu(hw[PRESTERA_PORT_JABBER_PKTS_CNT]);
1425 st->rx_error_frame_received =
1426 __le64_to_cpu(hw[PRESTERA_PORT_MAC_RCV_ERROR_CNT]);
1427 st->bad_crc = __le64_to_cpu(hw[PRESTERA_PORT_BAD_CRC_CNT]);
1428 st->collisions = __le64_to_cpu(hw[PRESTERA_PORT_COLLISIONS_CNT]);
1429 st->late_collision =
1430 __le64_to_cpu(hw[PRESTERA_PORT_LATE_COLLISIONS_CNT]);
1431 st->unicast_frames_received =
1432 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT]);
1433 st->unicast_frames_sent =
1434 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT]);
1435 st->sent_multiple =
1436 __le64_to_cpu(hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT]);
1437 st->sent_deferred =
1438 __le64_to_cpu(hw[PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT]);
1439 st->good_octets_sent =
1440 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT]);
1441
1442 return 0;
1443 }
1444
prestera_hw_port_learning_set(struct prestera_port * port,bool enable)1445 int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
1446 {
1447 struct prestera_msg_port_attr_req req = {
1448 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_LEARNING),
1449 .port = __cpu_to_le32(port->hw_id),
1450 .dev = __cpu_to_le32(port->dev_id),
1451 .param = {
1452 .learning = enable,
1453 }
1454 };
1455
1456 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1457 &req.cmd, sizeof(req));
1458 }
1459
prestera_hw_port_uc_flood_set(struct prestera_port * port,bool flood)1460 static int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood)
1461 {
1462 struct prestera_msg_port_attr_req req = {
1463 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1464 .port = __cpu_to_le32(port->hw_id),
1465 .dev = __cpu_to_le32(port->dev_id),
1466 .param = {
1467 .flood_ext = {
1468 .type = PRESTERA_PORT_FLOOD_TYPE_UC,
1469 .enable = flood,
1470 }
1471 }
1472 };
1473
1474 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1475 &req.cmd, sizeof(req));
1476 }
1477
prestera_hw_port_mc_flood_set(struct prestera_port * port,bool flood)1478 static int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood)
1479 {
1480 struct prestera_msg_port_attr_req req = {
1481 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1482 .port = __cpu_to_le32(port->hw_id),
1483 .dev = __cpu_to_le32(port->dev_id),
1484 .param = {
1485 .flood_ext = {
1486 .type = PRESTERA_PORT_FLOOD_TYPE_MC,
1487 .enable = flood,
1488 }
1489 }
1490 };
1491
1492 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1493 &req.cmd, sizeof(req));
1494 }
1495
prestera_hw_port_flood_set_v2(struct prestera_port * port,bool flood)1496 static int prestera_hw_port_flood_set_v2(struct prestera_port *port, bool flood)
1497 {
1498 struct prestera_msg_port_attr_req req = {
1499 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1500 .port = __cpu_to_le32(port->hw_id),
1501 .dev = __cpu_to_le32(port->dev_id),
1502 .param = {
1503 .flood = flood,
1504 }
1505 };
1506
1507 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1508 &req.cmd, sizeof(req));
1509 }
1510
prestera_hw_port_flood_set(struct prestera_port * port,unsigned long mask,unsigned long val)1511 int prestera_hw_port_flood_set(struct prestera_port *port, unsigned long mask,
1512 unsigned long val)
1513 {
1514 int err;
1515
1516 if (port->sw->dev->fw_rev.maj <= 2) {
1517 if (!(mask & BR_FLOOD))
1518 return 0;
1519
1520 return prestera_hw_port_flood_set_v2(port, val & BR_FLOOD);
1521 }
1522
1523 if (mask & BR_FLOOD) {
1524 err = prestera_hw_port_uc_flood_set(port, val & BR_FLOOD);
1525 if (err)
1526 goto err_uc_flood;
1527 }
1528
1529 if (mask & BR_MCAST_FLOOD) {
1530 err = prestera_hw_port_mc_flood_set(port, val & BR_MCAST_FLOOD);
1531 if (err)
1532 goto err_mc_flood;
1533 }
1534
1535 return 0;
1536
1537 err_mc_flood:
1538 prestera_hw_port_mc_flood_set(port, 0);
1539 err_uc_flood:
1540 if (mask & BR_FLOOD)
1541 prestera_hw_port_uc_flood_set(port, 0);
1542
1543 return err;
1544 }
1545
prestera_hw_vlan_create(struct prestera_switch * sw,u16 vid)1546 int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
1547 {
1548 struct prestera_msg_vlan_req req = {
1549 .vid = __cpu_to_le16(vid),
1550 };
1551
1552 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE,
1553 &req.cmd, sizeof(req));
1554 }
1555
prestera_hw_vlan_delete(struct prestera_switch * sw,u16 vid)1556 int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid)
1557 {
1558 struct prestera_msg_vlan_req req = {
1559 .vid = __cpu_to_le16(vid),
1560 };
1561
1562 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE,
1563 &req.cmd, sizeof(req));
1564 }
1565
prestera_hw_vlan_port_set(struct prestera_port * port,u16 vid,bool is_member,bool untagged)1566 int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid,
1567 bool is_member, bool untagged)
1568 {
1569 struct prestera_msg_vlan_req req = {
1570 .port = __cpu_to_le32(port->hw_id),
1571 .dev = __cpu_to_le32(port->dev_id),
1572 .vid = __cpu_to_le16(vid),
1573 .is_member = is_member,
1574 .is_tagged = !untagged,
1575 };
1576
1577 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET,
1578 &req.cmd, sizeof(req));
1579 }
1580
prestera_hw_vlan_port_vid_set(struct prestera_port * port,u16 vid)1581 int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid)
1582 {
1583 struct prestera_msg_vlan_req req = {
1584 .port = __cpu_to_le32(port->hw_id),
1585 .dev = __cpu_to_le32(port->dev_id),
1586 .vid = __cpu_to_le16(vid),
1587 };
1588
1589 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET,
1590 &req.cmd, sizeof(req));
1591 }
1592
prestera_hw_vlan_port_stp_set(struct prestera_port * port,u16 vid,u8 state)1593 int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state)
1594 {
1595 struct prestera_msg_stp_req req = {
1596 .port = __cpu_to_le32(port->hw_id),
1597 .dev = __cpu_to_le32(port->dev_id),
1598 .vid = __cpu_to_le16(vid),
1599 .state = state,
1600 };
1601
1602 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET,
1603 &req.cmd, sizeof(req));
1604 }
1605
prestera_hw_fdb_add(struct prestera_port * port,const unsigned char * mac,u16 vid,bool dynamic)1606 int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac,
1607 u16 vid, bool dynamic)
1608 {
1609 struct prestera_msg_fdb_req req = {
1610 .dest = {
1611 .dev = __cpu_to_le32(port->dev_id),
1612 .port = __cpu_to_le32(port->hw_id),
1613 },
1614 .vid = __cpu_to_le16(vid),
1615 .dynamic = dynamic,
1616 };
1617
1618 ether_addr_copy(req.mac, mac);
1619
1620 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD,
1621 &req.cmd, sizeof(req));
1622 }
1623
prestera_hw_fdb_del(struct prestera_port * port,const unsigned char * mac,u16 vid)1624 int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac,
1625 u16 vid)
1626 {
1627 struct prestera_msg_fdb_req req = {
1628 .dest = {
1629 .dev = __cpu_to_le32(port->dev_id),
1630 .port = __cpu_to_le32(port->hw_id),
1631 },
1632 .vid = __cpu_to_le16(vid),
1633 };
1634
1635 ether_addr_copy(req.mac, mac);
1636
1637 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1638 &req.cmd, sizeof(req));
1639 }
1640
prestera_hw_lag_fdb_add(struct prestera_switch * sw,u16 lag_id,const unsigned char * mac,u16 vid,bool dynamic)1641 int prestera_hw_lag_fdb_add(struct prestera_switch *sw, u16 lag_id,
1642 const unsigned char *mac, u16 vid, bool dynamic)
1643 {
1644 struct prestera_msg_fdb_req req = {
1645 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1646 .dest = {
1647 .lag_id = __cpu_to_le16(lag_id),
1648 },
1649 .vid = __cpu_to_le16(vid),
1650 .dynamic = dynamic,
1651 };
1652
1653 ether_addr_copy(req.mac, mac);
1654
1655 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_ADD,
1656 &req.cmd, sizeof(req));
1657 }
1658
prestera_hw_lag_fdb_del(struct prestera_switch * sw,u16 lag_id,const unsigned char * mac,u16 vid)1659 int prestera_hw_lag_fdb_del(struct prestera_switch *sw, u16 lag_id,
1660 const unsigned char *mac, u16 vid)
1661 {
1662 struct prestera_msg_fdb_req req = {
1663 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1664 .dest = {
1665 .lag_id = __cpu_to_le16(lag_id),
1666 },
1667 .vid = __cpu_to_le16(vid),
1668 };
1669
1670 ether_addr_copy(req.mac, mac);
1671
1672 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1673 &req.cmd, sizeof(req));
1674 }
1675
prestera_hw_fdb_flush_port(struct prestera_port * port,u32 mode)1676 int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode)
1677 {
1678 struct prestera_msg_fdb_req req = {
1679 .dest = {
1680 .dev = __cpu_to_le32(port->dev_id),
1681 .port = __cpu_to_le32(port->hw_id),
1682 },
1683 .flush_mode = __cpu_to_le32(mode),
1684 };
1685
1686 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1687 &req.cmd, sizeof(req));
1688 }
1689
prestera_hw_fdb_flush_vlan(struct prestera_switch * sw,u16 vid,u32 mode)1690 int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode)
1691 {
1692 struct prestera_msg_fdb_req req = {
1693 .vid = __cpu_to_le16(vid),
1694 .flush_mode = __cpu_to_le32(mode),
1695 };
1696
1697 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN,
1698 &req.cmd, sizeof(req));
1699 }
1700
prestera_hw_fdb_flush_port_vlan(struct prestera_port * port,u16 vid,u32 mode)1701 int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
1702 u32 mode)
1703 {
1704 struct prestera_msg_fdb_req req = {
1705 .dest = {
1706 .dev = __cpu_to_le32(port->dev_id),
1707 .port = __cpu_to_le32(port->hw_id),
1708 },
1709 .vid = __cpu_to_le16(vid),
1710 .flush_mode = __cpu_to_le32(mode),
1711 };
1712
1713 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1714 &req.cmd, sizeof(req));
1715 }
1716
prestera_hw_fdb_flush_lag(struct prestera_switch * sw,u16 lag_id,u32 mode)1717 int prestera_hw_fdb_flush_lag(struct prestera_switch *sw, u16 lag_id,
1718 u32 mode)
1719 {
1720 struct prestera_msg_fdb_req req = {
1721 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1722 .dest = {
1723 .lag_id = __cpu_to_le16(lag_id),
1724 },
1725 .flush_mode = __cpu_to_le32(mode),
1726 };
1727
1728 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1729 &req.cmd, sizeof(req));
1730 }
1731
prestera_hw_fdb_flush_lag_vlan(struct prestera_switch * sw,u16 lag_id,u16 vid,u32 mode)1732 int prestera_hw_fdb_flush_lag_vlan(struct prestera_switch *sw,
1733 u16 lag_id, u16 vid, u32 mode)
1734 {
1735 struct prestera_msg_fdb_req req = {
1736 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1737 .dest = {
1738 .lag_id = __cpu_to_le16(lag_id),
1739 },
1740 .vid = __cpu_to_le16(vid),
1741 .flush_mode = __cpu_to_le32(mode),
1742 };
1743
1744 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1745 &req.cmd, sizeof(req));
1746 }
1747
prestera_hw_bridge_create(struct prestera_switch * sw,u16 * bridge_id)1748 int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id)
1749 {
1750 struct prestera_msg_bridge_resp resp;
1751 struct prestera_msg_bridge_req req;
1752 int err;
1753
1754 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE,
1755 &req.cmd, sizeof(req),
1756 &resp.ret, sizeof(resp));
1757 if (err)
1758 return err;
1759
1760 *bridge_id = __le16_to_cpu(resp.bridge);
1761
1762 return 0;
1763 }
1764
prestera_hw_bridge_delete(struct prestera_switch * sw,u16 bridge_id)1765 int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id)
1766 {
1767 struct prestera_msg_bridge_req req = {
1768 .bridge = __cpu_to_le16(bridge_id),
1769 };
1770
1771 return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE,
1772 &req.cmd, sizeof(req));
1773 }
1774
prestera_hw_bridge_port_add(struct prestera_port * port,u16 bridge_id)1775 int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id)
1776 {
1777 struct prestera_msg_bridge_req req = {
1778 .bridge = __cpu_to_le16(bridge_id),
1779 .port = __cpu_to_le32(port->hw_id),
1780 .dev = __cpu_to_le32(port->dev_id),
1781 };
1782
1783 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD,
1784 &req.cmd, sizeof(req));
1785 }
1786
prestera_hw_bridge_port_delete(struct prestera_port * port,u16 bridge_id)1787 int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)
1788 {
1789 struct prestera_msg_bridge_req req = {
1790 .bridge = __cpu_to_le16(bridge_id),
1791 .port = __cpu_to_le32(port->hw_id),
1792 .dev = __cpu_to_le32(port->dev_id),
1793 };
1794
1795 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE,
1796 &req.cmd, sizeof(req));
1797 }
1798
prestera_hw_rxtx_init(struct prestera_switch * sw,struct prestera_rxtx_params * params)1799 int prestera_hw_rxtx_init(struct prestera_switch *sw,
1800 struct prestera_rxtx_params *params)
1801 {
1802 struct prestera_msg_rxtx_resp resp;
1803 struct prestera_msg_rxtx_req req;
1804 int err;
1805
1806 req.use_sdma = params->use_sdma;
1807
1808 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT,
1809 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1810 if (err)
1811 return err;
1812
1813 params->map_addr = __le32_to_cpu(resp.map_addr);
1814
1815 return 0;
1816 }
1817
prestera_hw_lag_member_add(struct prestera_port * port,u16 lag_id)1818 int prestera_hw_lag_member_add(struct prestera_port *port, u16 lag_id)
1819 {
1820 struct prestera_msg_lag_req req = {
1821 .port = __cpu_to_le32(port->hw_id),
1822 .dev = __cpu_to_le32(port->dev_id),
1823 .lag_id = __cpu_to_le16(lag_id),
1824 };
1825
1826 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_ADD,
1827 &req.cmd, sizeof(req));
1828 }
1829
prestera_hw_lag_member_del(struct prestera_port * port,u16 lag_id)1830 int prestera_hw_lag_member_del(struct prestera_port *port, u16 lag_id)
1831 {
1832 struct prestera_msg_lag_req req = {
1833 .port = __cpu_to_le32(port->hw_id),
1834 .dev = __cpu_to_le32(port->dev_id),
1835 .lag_id = __cpu_to_le16(lag_id),
1836 };
1837
1838 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE,
1839 &req.cmd, sizeof(req));
1840 }
1841
prestera_hw_lag_member_enable(struct prestera_port * port,u16 lag_id,bool enable)1842 int prestera_hw_lag_member_enable(struct prestera_port *port, u16 lag_id,
1843 bool enable)
1844 {
1845 struct prestera_msg_lag_req req = {
1846 .port = __cpu_to_le32(port->hw_id),
1847 .dev = __cpu_to_le32(port->dev_id),
1848 .lag_id = __cpu_to_le16(lag_id),
1849 };
1850 u32 cmd;
1851
1852 cmd = enable ? PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE :
1853 PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE;
1854
1855 return prestera_cmd(port->sw, cmd, &req.cmd, sizeof(req));
1856 }
1857
1858 int
prestera_hw_cpu_code_counters_get(struct prestera_switch * sw,u8 code,enum prestera_hw_cpu_code_cnt_t counter_type,u64 * packet_count)1859 prestera_hw_cpu_code_counters_get(struct prestera_switch *sw, u8 code,
1860 enum prestera_hw_cpu_code_cnt_t counter_type,
1861 u64 *packet_count)
1862 {
1863 struct prestera_msg_cpu_code_counter_req req = {
1864 .counter_type = counter_type,
1865 .code = code,
1866 };
1867 struct mvsw_msg_cpu_code_counter_ret resp;
1868 int err;
1869
1870 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET,
1871 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1872 if (err)
1873 return err;
1874
1875 *packet_count = __le64_to_cpu(resp.packet_count);
1876
1877 return 0;
1878 }
1879
prestera_hw_event_handler_register(struct prestera_switch * sw,enum prestera_event_type type,prestera_event_cb_t fn,void * arg)1880 int prestera_hw_event_handler_register(struct prestera_switch *sw,
1881 enum prestera_event_type type,
1882 prestera_event_cb_t fn,
1883 void *arg)
1884 {
1885 struct prestera_fw_event_handler *eh;
1886
1887 eh = __find_event_handler(sw, type);
1888 if (eh)
1889 return -EEXIST;
1890
1891 eh = kmalloc(sizeof(*eh), GFP_KERNEL);
1892 if (!eh)
1893 return -ENOMEM;
1894
1895 eh->type = type;
1896 eh->func = fn;
1897 eh->arg = arg;
1898
1899 INIT_LIST_HEAD(&eh->list);
1900
1901 list_add_rcu(&eh->list, &sw->event_handlers);
1902
1903 return 0;
1904 }
1905
prestera_hw_event_handler_unregister(struct prestera_switch * sw,enum prestera_event_type type,prestera_event_cb_t fn)1906 void prestera_hw_event_handler_unregister(struct prestera_switch *sw,
1907 enum prestera_event_type type,
1908 prestera_event_cb_t fn)
1909 {
1910 struct prestera_fw_event_handler *eh;
1911
1912 eh = __find_event_handler(sw, type);
1913 if (!eh)
1914 return;
1915
1916 list_del_rcu(&eh->list);
1917 kfree_rcu(eh, rcu);
1918 }
1919