GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / net / ethernet / marvell / prestera / prestera_hw.c
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 #include "prestera_counter.h"
13 #include "prestera_router_hw.h"
14
15 #define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
16
17 #define PRESTERA_MIN_MTU 64
18
19 #define PRESTERA_MSG_CHUNK_SIZE 1024
20
21 enum prestera_cmd_type_t {
22         PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1,
23         PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2,
24
25         PRESTERA_CMD_TYPE_PORT_ATTR_SET = 0x100,
26         PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101,
27         PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110,
28
29         PRESTERA_CMD_TYPE_VLAN_CREATE = 0x200,
30         PRESTERA_CMD_TYPE_VLAN_DELETE = 0x201,
31         PRESTERA_CMD_TYPE_VLAN_PORT_SET = 0x202,
32         PRESTERA_CMD_TYPE_VLAN_PVID_SET = 0x203,
33
34         PRESTERA_CMD_TYPE_FDB_ADD = 0x300,
35         PRESTERA_CMD_TYPE_FDB_DELETE = 0x301,
36         PRESTERA_CMD_TYPE_FDB_FLUSH_PORT = 0x310,
37         PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN = 0x311,
38         PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN = 0x312,
39
40         PRESTERA_CMD_TYPE_BRIDGE_CREATE = 0x400,
41         PRESTERA_CMD_TYPE_BRIDGE_DELETE = 0x401,
42         PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD = 0x402,
43         PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE = 0x403,
44
45         PRESTERA_CMD_TYPE_COUNTER_GET = 0x510,
46         PRESTERA_CMD_TYPE_COUNTER_ABORT = 0x511,
47         PRESTERA_CMD_TYPE_COUNTER_TRIGGER = 0x512,
48         PRESTERA_CMD_TYPE_COUNTER_BLOCK_GET = 0x513,
49         PRESTERA_CMD_TYPE_COUNTER_BLOCK_RELEASE = 0x514,
50         PRESTERA_CMD_TYPE_COUNTER_CLEAR = 0x515,
51
52         PRESTERA_CMD_TYPE_VTCAM_CREATE = 0x540,
53         PRESTERA_CMD_TYPE_VTCAM_DESTROY = 0x541,
54         PRESTERA_CMD_TYPE_VTCAM_RULE_ADD = 0x550,
55         PRESTERA_CMD_TYPE_VTCAM_RULE_DELETE = 0x551,
56         PRESTERA_CMD_TYPE_VTCAM_IFACE_BIND = 0x560,
57         PRESTERA_CMD_TYPE_VTCAM_IFACE_UNBIND = 0x561,
58
59         PRESTERA_CMD_TYPE_ROUTER_RIF_CREATE = 0x600,
60         PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE = 0x601,
61         PRESTERA_CMD_TYPE_ROUTER_LPM_ADD = 0x610,
62         PRESTERA_CMD_TYPE_ROUTER_LPM_DELETE = 0x611,
63         PRESTERA_CMD_TYPE_ROUTER_NH_GRP_SET = 0x622,
64         PRESTERA_CMD_TYPE_ROUTER_NH_GRP_BLK_GET = 0x645,
65         PRESTERA_CMD_TYPE_ROUTER_NH_GRP_ADD = 0x623,
66         PRESTERA_CMD_TYPE_ROUTER_NH_GRP_DELETE = 0x624,
67         PRESTERA_CMD_TYPE_ROUTER_VR_CREATE = 0x630,
68         PRESTERA_CMD_TYPE_ROUTER_VR_DELETE = 0x631,
69
70         PRESTERA_CMD_TYPE_FLOOD_DOMAIN_CREATE = 0x700,
71         PRESTERA_CMD_TYPE_FLOOD_DOMAIN_DESTROY = 0x701,
72         PRESTERA_CMD_TYPE_FLOOD_DOMAIN_PORTS_SET = 0x702,
73         PRESTERA_CMD_TYPE_FLOOD_DOMAIN_PORTS_RESET = 0x703,
74
75         PRESTERA_CMD_TYPE_MDB_CREATE = 0x704,
76         PRESTERA_CMD_TYPE_MDB_DESTROY = 0x705,
77
78         PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
79
80         PRESTERA_CMD_TYPE_LAG_MEMBER_ADD = 0x900,
81         PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE = 0x901,
82         PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE = 0x902,
83         PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE = 0x903,
84
85         PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
86
87         PRESTERA_CMD_TYPE_SPAN_GET = 0x1100,
88         PRESTERA_CMD_TYPE_SPAN_INGRESS_BIND = 0x1101,
89         PRESTERA_CMD_TYPE_SPAN_INGRESS_UNBIND = 0x1102,
90         PRESTERA_CMD_TYPE_SPAN_RELEASE = 0x1103,
91         PRESTERA_CMD_TYPE_SPAN_EGRESS_BIND = 0x1104,
92         PRESTERA_CMD_TYPE_SPAN_EGRESS_UNBIND = 0x1105,
93
94         PRESTERA_CMD_TYPE_POLICER_CREATE = 0x1500,
95         PRESTERA_CMD_TYPE_POLICER_RELEASE = 0x1501,
96         PRESTERA_CMD_TYPE_POLICER_SET = 0x1502,
97
98         PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET = 0x2000,
99
100         PRESTERA_CMD_TYPE_ACK = 0x10000,
101         PRESTERA_CMD_TYPE_MAX
102 };
103
104 enum {
105         PRESTERA_CMD_PORT_ATTR_ADMIN_STATE = 1,
106         PRESTERA_CMD_PORT_ATTR_MTU = 3,
107         PRESTERA_CMD_PORT_ATTR_MAC = 4,
108         PRESTERA_CMD_PORT_ATTR_SPEED = 5,
109         PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6,
110         PRESTERA_CMD_PORT_ATTR_LEARNING = 7,
111         PRESTERA_CMD_PORT_ATTR_FLOOD = 8,
112         PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9,
113         PRESTERA_CMD_PORT_ATTR_LOCKED = 10,
114         PRESTERA_CMD_PORT_ATTR_PHY_MODE = 12,
115         PRESTERA_CMD_PORT_ATTR_TYPE = 13,
116         PRESTERA_CMD_PORT_ATTR_STATS = 17,
117         PRESTERA_CMD_PORT_ATTR_MAC_AUTONEG_RESTART = 18,
118         PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART = 19,
119         PRESTERA_CMD_PORT_ATTR_MAC_MODE = 22,
120 };
121
122 enum {
123         PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
124         PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
125 };
126
127 enum {
128         PRESTERA_CMD_ACK_OK,
129         PRESTERA_CMD_ACK_FAILED,
130
131         PRESTERA_CMD_ACK_MAX
132 };
133
134 enum {
135         PRESTERA_PORT_TP_NA,
136         PRESTERA_PORT_TP_MDI,
137         PRESTERA_PORT_TP_MDIX,
138         PRESTERA_PORT_TP_AUTO,
139 };
140
141 enum {
142         PRESTERA_PORT_FLOOD_TYPE_UC = 0,
143         PRESTERA_PORT_FLOOD_TYPE_MC = 1,
144 };
145
146 enum {
147         PRESTERA_PORT_GOOD_OCTETS_RCV_CNT,
148         PRESTERA_PORT_BAD_OCTETS_RCV_CNT,
149         PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT,
150         PRESTERA_PORT_BRDC_PKTS_RCV_CNT,
151         PRESTERA_PORT_MC_PKTS_RCV_CNT,
152         PRESTERA_PORT_PKTS_64L_CNT,
153         PRESTERA_PORT_PKTS_65TO127L_CNT,
154         PRESTERA_PORT_PKTS_128TO255L_CNT,
155         PRESTERA_PORT_PKTS_256TO511L_CNT,
156         PRESTERA_PORT_PKTS_512TO1023L_CNT,
157         PRESTERA_PORT_PKTS_1024TOMAXL_CNT,
158         PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT,
159         PRESTERA_PORT_MC_PKTS_SENT_CNT,
160         PRESTERA_PORT_BRDC_PKTS_SENT_CNT,
161         PRESTERA_PORT_FC_SENT_CNT,
162         PRESTERA_PORT_GOOD_FC_RCV_CNT,
163         PRESTERA_PORT_DROP_EVENTS_CNT,
164         PRESTERA_PORT_UNDERSIZE_PKTS_CNT,
165         PRESTERA_PORT_FRAGMENTS_PKTS_CNT,
166         PRESTERA_PORT_OVERSIZE_PKTS_CNT,
167         PRESTERA_PORT_JABBER_PKTS_CNT,
168         PRESTERA_PORT_MAC_RCV_ERROR_CNT,
169         PRESTERA_PORT_BAD_CRC_CNT,
170         PRESTERA_PORT_COLLISIONS_CNT,
171         PRESTERA_PORT_LATE_COLLISIONS_CNT,
172         PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT,
173         PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT,
174         PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT,
175         PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT,
176         PRESTERA_PORT_GOOD_OCTETS_SENT_CNT,
177
178         PRESTERA_PORT_CNT_MAX
179 };
180
181 enum {
182         PRESTERA_FC_NONE,
183         PRESTERA_FC_SYMMETRIC,
184         PRESTERA_FC_ASYMMETRIC,
185         PRESTERA_FC_SYMM_ASYMM,
186 };
187
188 enum {
189         PRESTERA_POLICER_MODE_SR_TCM
190 };
191
192 enum {
193         PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT = 0,
194         PRESTERA_HW_FDB_ENTRY_TYPE_LAG = 1,
195         PRESTERA_HW_FDB_ENTRY_TYPE_MAX = 2,
196 };
197
198 struct prestera_fw_event_handler {
199         struct list_head list;
200         struct rcu_head rcu;
201         enum prestera_event_type type;
202         prestera_event_cb_t func;
203         void *arg;
204 };
205
206 enum {
207         PRESTERA_HW_FLOOD_DOMAIN_PORT_TYPE_REG_PORT = 0,
208         PRESTERA_HW_FLOOD_DOMAIN_PORT_TYPE_LAG = 1,
209         PRESTERA_HW_FLOOD_DOMAIN_PORT_TYPE_MAX = 2,
210 };
211
212 struct prestera_msg_cmd {
213         __le32 type;
214 };
215
216 struct prestera_msg_ret {
217         struct prestera_msg_cmd cmd;
218         __le32 status;
219 };
220
221 struct prestera_msg_common_req {
222         struct prestera_msg_cmd cmd;
223 };
224
225 struct prestera_msg_common_resp {
226         struct prestera_msg_ret ret;
227 };
228
229 struct prestera_msg_switch_attr_req {
230         struct prestera_msg_cmd cmd;
231         __le32 attr;
232         union {
233                 __le32 ageing_timeout_ms;
234                 struct {
235                         u8 mac[ETH_ALEN];
236                         u8 __pad[2];
237                 };
238         } param;
239 };
240
241 struct prestera_msg_switch_init_resp {
242         struct prestera_msg_ret ret;
243         __le32 port_count;
244         __le32 mtu_max;
245         __le32 size_tbl_router_nexthop;
246         u8 switch_id;
247         u8 lag_max;
248         u8 lag_member_max;
249 };
250
251 struct prestera_msg_event_port_param {
252         union {
253                 struct {
254                         __le32 mode;
255                         __le32 speed;
256                         u8 oper;
257                         u8 duplex;
258                         u8 fc;
259                         u8 fec;
260                 } mac;
261                 struct {
262                         __le64 lmode_bmap;
263                         u8 mdix;
264                         u8 fc;
265                         u8 __pad[2];
266                 } __packed phy; /* make sure always 12 bytes size */
267         };
268 };
269
270 struct prestera_msg_port_cap_param {
271         __le64 link_mode;
272         u8 type;
273         u8 fec;
274         u8 fc;
275         u8 transceiver;
276 };
277
278 struct prestera_msg_port_flood_param {
279         u8 type;
280         u8 enable;
281         u8 __pad[2];
282 };
283
284 union prestera_msg_port_param {
285         __le32 mtu;
286         __le32 speed;
287         __le32 link_mode;
288         u8 admin_state;
289         u8 oper_state;
290         u8 mac[ETH_ALEN];
291         u8 accept_frm_type;
292         u8 learning;
293         u8 flood;
294         u8 type;
295         u8 duplex;
296         u8 fec;
297         u8 fc;
298         u8 br_locked;
299         union {
300                 struct {
301                         u8 admin;
302                         u8 fc;
303                         u8 ap_enable;
304                         u8 __reserved[5];
305                         union {
306                                 struct {
307                                         __le32 mode;
308                                         __le32 speed;
309                                         u8 inband;
310                                         u8 duplex;
311                                         u8 fec;
312                                         u8 fec_supp;
313                                 } reg_mode;
314                                 struct {
315                                         __le32 mode;
316                                         __le32 speed;
317                                         u8 fec;
318                                         u8 fec_supp;
319                                         u8 __pad[2];
320                                 } ap_modes[PRESTERA_AP_PORT_MAX];
321                         };
322                 } mac;
323                 struct {
324                         __le64 modes;
325                         __le32 mode;
326                         u8 admin;
327                         u8 adv_enable;
328                         u8 mdix;
329                         u8 __pad;
330                 } phy;
331         } link;
332
333         struct prestera_msg_port_cap_param cap;
334         struct prestera_msg_port_flood_param flood_ext;
335         struct prestera_msg_event_port_param link_evt;
336 };
337
338 struct prestera_msg_port_attr_req {
339         struct prestera_msg_cmd cmd;
340         __le32 attr;
341         __le32 port;
342         __le32 dev;
343         union prestera_msg_port_param param;
344 };
345
346 struct prestera_msg_port_attr_resp {
347         struct prestera_msg_ret ret;
348         union prestera_msg_port_param param;
349 };
350
351 struct prestera_msg_port_stats_resp {
352         struct prestera_msg_ret ret;
353         __le64 stats[PRESTERA_PORT_CNT_MAX];
354 };
355
356 struct prestera_msg_port_info_req {
357         struct prestera_msg_cmd cmd;
358         __le32 port;
359 };
360
361 struct prestera_msg_port_info_resp {
362         struct prestera_msg_ret ret;
363         __le32 hw_id;
364         __le32 dev_id;
365         __le16 fp_id;
366         u8 pad[2];
367 };
368
369 struct prestera_msg_vlan_req {
370         struct prestera_msg_cmd cmd;
371         __le32 port;
372         __le32 dev;
373         __le16 vid;
374         u8 is_member;
375         u8 is_tagged;
376 };
377
378 struct prestera_msg_fdb_req {
379         struct prestera_msg_cmd cmd;
380         __le32 flush_mode;
381         union {
382                 struct {
383                         __le32 port;
384                         __le32 dev;
385                 };
386                 __le16 lag_id;
387         } dest;
388         __le16 vid;
389         u8 dest_type;
390         u8 dynamic;
391         u8 mac[ETH_ALEN];
392         u8 __pad[2];
393 };
394
395 struct prestera_msg_bridge_req {
396         struct prestera_msg_cmd cmd;
397         __le32 port;
398         __le32 dev;
399         __le16 bridge;
400         u8 pad[2];
401 };
402
403 struct prestera_msg_bridge_resp {
404         struct prestera_msg_ret ret;
405         __le16 bridge;
406         u8 pad[2];
407 };
408
409 struct prestera_msg_vtcam_create_req {
410         struct prestera_msg_cmd cmd;
411         __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
412         u8 direction;
413         u8 lookup;
414         u8 pad[2];
415 };
416
417 struct prestera_msg_vtcam_destroy_req {
418         struct prestera_msg_cmd cmd;
419         __le32 vtcam_id;
420 };
421
422 struct prestera_msg_vtcam_rule_add_req {
423         struct prestera_msg_cmd cmd;
424         __le32 key[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
425         __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
426         __le32 vtcam_id;
427         __le32 prio;
428         __le32 n_act;
429 };
430
431 struct prestera_msg_vtcam_rule_del_req {
432         struct prestera_msg_cmd cmd;
433         __le32 vtcam_id;
434         __le32 id;
435 };
436
437 struct prestera_msg_vtcam_bind_req {
438         struct prestera_msg_cmd cmd;
439         union {
440                 struct {
441                         __le32 hw_id;
442                         __le32 dev_id;
443                 } port;
444                 __le32 index;
445         };
446         __le32 vtcam_id;
447         __le16 pcl_id;
448         __le16 type;
449 };
450
451 struct prestera_msg_vtcam_resp {
452         struct prestera_msg_ret ret;
453         __le32 vtcam_id;
454         __le32 rule_id;
455 };
456
457 struct prestera_msg_acl_action {
458         __le32 id;
459         __le32 __reserved;
460         union {
461                 struct {
462                         __le32 index;
463                 } jump;
464                 struct {
465                         __le32 id;
466                 } police;
467                 struct {
468                         __le32 id;
469                 } count;
470                 __le32 reserved[6];
471         };
472 };
473
474 struct prestera_msg_counter_req {
475         struct prestera_msg_cmd cmd;
476         __le32 client;
477         __le32 block_id;
478         __le32 num_counters;
479 };
480
481 struct prestera_msg_counter_stats {
482         __le64 packets;
483         __le64 bytes;
484 };
485
486 struct prestera_msg_counter_resp {
487         struct prestera_msg_ret ret;
488         __le32 block_id;
489         __le32 offset;
490         __le32 num_counters;
491         __le32 done;
492         struct prestera_msg_counter_stats stats[];
493 };
494
495 struct prestera_msg_span_req {
496         struct prestera_msg_cmd cmd;
497         __le32 port;
498         __le32 dev;
499         u8 id;
500         u8 pad[3];
501 };
502
503 struct prestera_msg_span_resp {
504         struct prestera_msg_ret ret;
505         u8 id;
506         u8 pad[3];
507 };
508
509 struct prestera_msg_stp_req {
510         struct prestera_msg_cmd cmd;
511         __le32 port;
512         __le32 dev;
513         __le16 vid;
514         u8 state;
515         u8 __pad;
516 };
517
518 struct prestera_msg_rxtx_req {
519         struct prestera_msg_cmd cmd;
520         u8 use_sdma;
521         u8 pad[3];
522 };
523
524 struct prestera_msg_rxtx_resp {
525         struct prestera_msg_ret ret;
526         __le32 map_addr;
527 };
528
529 struct prestera_msg_iface {
530         union {
531                 struct {
532                         __le32 dev;
533                         __le32 port;
534                 };
535                 __le16 lag_id;
536         };
537         __le16 vr_id;
538         __le16 vid;
539         u8 type;
540         u8 __pad[3];
541 };
542
543 struct prestera_msg_ip_addr {
544         union {
545                 __be32 ipv4;
546                 __be32 ipv6[4];
547         } u;
548         u8 v; /* e.g. PRESTERA_IPV4 */
549         u8 __pad[3];
550 };
551
552 struct prestera_msg_nh {
553         struct prestera_msg_iface oif;
554         __le32 hw_id;
555         u8 mac[ETH_ALEN];
556         u8 is_active;
557         u8 pad;
558 };
559
560 struct prestera_msg_rif_req {
561         struct prestera_msg_cmd cmd;
562         struct prestera_msg_iface iif;
563         __le32 mtu;
564         __le16 rif_id;
565         __le16 __reserved;
566         u8 mac[ETH_ALEN];
567         u8 __pad[2];
568 };
569
570 struct prestera_msg_rif_resp {
571         struct prestera_msg_ret ret;
572         __le16 rif_id;
573         u8 __pad[2];
574 };
575
576 struct prestera_msg_lpm_req {
577         struct prestera_msg_cmd cmd;
578         struct prestera_msg_ip_addr dst;
579         __le32 grp_id;
580         __le32 dst_len;
581         __le16 vr_id;
582         u8 __pad[2];
583 };
584
585 struct prestera_msg_nh_req {
586         struct prestera_msg_cmd cmd;
587         struct prestera_msg_nh nh[PRESTERA_NHGR_SIZE_MAX];
588         __le32 size;
589         __le32 grp_id;
590 };
591
592 struct prestera_msg_nh_chunk_req {
593         struct prestera_msg_cmd cmd;
594         __le32 offset;
595 };
596
597 struct prestera_msg_nh_chunk_resp {
598         struct prestera_msg_ret ret;
599         u8 hw_state[PRESTERA_MSG_CHUNK_SIZE];
600 };
601
602 struct prestera_msg_nh_grp_req {
603         struct prestera_msg_cmd cmd;
604         __le32 grp_id;
605         __le32 size;
606 };
607
608 struct prestera_msg_nh_grp_resp {
609         struct prestera_msg_ret ret;
610         __le32 grp_id;
611 };
612
613 struct prestera_msg_vr_req {
614         struct prestera_msg_cmd cmd;
615         __le16 vr_id;
616         u8 __pad[2];
617 };
618
619 struct prestera_msg_vr_resp {
620         struct prestera_msg_ret ret;
621         __le16 vr_id;
622         u8 __pad[2];
623 };
624
625 struct prestera_msg_lag_req {
626         struct prestera_msg_cmd cmd;
627         __le32 port;
628         __le32 dev;
629         __le16 lag_id;
630         u8 pad[2];
631 };
632
633 struct prestera_msg_cpu_code_counter_req {
634         struct prestera_msg_cmd cmd;
635         u8 counter_type;
636         u8 code;
637         u8 pad[2];
638 };
639
640 struct mvsw_msg_cpu_code_counter_ret {
641         struct prestera_msg_ret ret;
642         __le64 packet_count;
643 };
644
645 struct prestera_msg_policer_req {
646         struct prestera_msg_cmd cmd;
647         __le32 id;
648         union {
649                 struct {
650                         __le64 cir;
651                         __le32 cbs;
652                 } __packed sr_tcm; /* make sure always 12 bytes size */
653                 __le32 reserved[6];
654         };
655         u8 mode;
656         u8 type;
657         u8 pad[2];
658 };
659
660 struct prestera_msg_policer_resp {
661         struct prestera_msg_ret ret;
662         __le32 id;
663 };
664
665 struct prestera_msg_event {
666         __le16 type;
667         __le16 id;
668 };
669
670 struct prestera_msg_event_port {
671         struct prestera_msg_event id;
672         __le32 port_id;
673         struct prestera_msg_event_port_param param;
674 };
675
676 union prestera_msg_event_fdb_param {
677         u8 mac[ETH_ALEN];
678 };
679
680 struct prestera_msg_event_fdb {
681         struct prestera_msg_event id;
682         __le32 vid;
683         union {
684                 __le32 port_id;
685                 __le16 lag_id;
686         } dest;
687         union prestera_msg_event_fdb_param param;
688         u8 dest_type;
689 };
690
691 struct prestera_msg_flood_domain_create_req {
692         struct prestera_msg_cmd cmd;
693 };
694
695 struct prestera_msg_flood_domain_create_resp {
696         struct prestera_msg_ret ret;
697         __le32 flood_domain_idx;
698 };
699
700 struct prestera_msg_flood_domain_destroy_req {
701         struct prestera_msg_cmd cmd;
702         __le32 flood_domain_idx;
703 };
704
705 struct prestera_msg_flood_domain_ports_set_req {
706         struct prestera_msg_cmd cmd;
707         __le32 flood_domain_idx;
708         __le32 ports_num;
709 };
710
711 struct prestera_msg_flood_domain_ports_reset_req {
712         struct prestera_msg_cmd cmd;
713         __le32 flood_domain_idx;
714 };
715
716 struct prestera_msg_flood_domain_port {
717         union {
718                 struct {
719                         __le32 port_num;
720                         __le32 dev_num;
721                 };
722                 __le16 lag_id;
723         };
724         __le16 vid;
725         __le16 port_type;
726 };
727
728 struct prestera_msg_mdb_create_req {
729         struct prestera_msg_cmd cmd;
730         __le32 flood_domain_idx;
731         __le16 vid;
732         u8 mac[ETH_ALEN];
733 };
734
735 struct prestera_msg_mdb_destroy_req {
736         struct prestera_msg_cmd cmd;
737         __le32 flood_domain_idx;
738         __le16 vid;
739         u8 mac[ETH_ALEN];
740 };
741
742 static void prestera_hw_build_tests(void)
743 {
744         /* check requests */
745         BUILD_BUG_ON(sizeof(struct prestera_msg_common_req) != 4);
746         BUILD_BUG_ON(sizeof(struct prestera_msg_switch_attr_req) != 16);
747         BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_req) != 144);
748         BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_req) != 8);
749         BUILD_BUG_ON(sizeof(struct prestera_msg_vlan_req) != 16);
750         BUILD_BUG_ON(sizeof(struct prestera_msg_fdb_req) != 28);
751         BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_req) != 16);
752         BUILD_BUG_ON(sizeof(struct prestera_msg_span_req) != 16);
753         BUILD_BUG_ON(sizeof(struct prestera_msg_stp_req) != 16);
754         BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_req) != 8);
755         BUILD_BUG_ON(sizeof(struct prestera_msg_lag_req) != 16);
756         BUILD_BUG_ON(sizeof(struct prestera_msg_cpu_code_counter_req) != 8);
757         BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_create_req) != 84);
758         BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_destroy_req) != 8);
759         BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_rule_add_req) != 168);
760         BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_rule_del_req) != 12);
761         BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_bind_req) != 20);
762         BUILD_BUG_ON(sizeof(struct prestera_msg_acl_action) != 32);
763         BUILD_BUG_ON(sizeof(struct prestera_msg_counter_req) != 16);
764         BUILD_BUG_ON(sizeof(struct prestera_msg_counter_stats) != 16);
765         BUILD_BUG_ON(sizeof(struct prestera_msg_rif_req) != 36);
766         BUILD_BUG_ON(sizeof(struct prestera_msg_vr_req) != 8);
767         BUILD_BUG_ON(sizeof(struct prestera_msg_lpm_req) != 36);
768         BUILD_BUG_ON(sizeof(struct prestera_msg_policer_req) != 36);
769         BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_create_req) != 4);
770         BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_destroy_req) != 8);
771         BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_ports_set_req) != 12);
772         BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_ports_reset_req) != 8);
773         BUILD_BUG_ON(sizeof(struct prestera_msg_mdb_create_req) != 16);
774         BUILD_BUG_ON(sizeof(struct prestera_msg_mdb_destroy_req) != 16);
775         BUILD_BUG_ON(sizeof(struct prestera_msg_nh_req) != 124);
776         BUILD_BUG_ON(sizeof(struct prestera_msg_nh_chunk_req) != 8);
777         BUILD_BUG_ON(sizeof(struct prestera_msg_nh_grp_req) != 12);
778
779         /*  structure that are part of req/resp fw messages */
780         BUILD_BUG_ON(sizeof(struct prestera_msg_iface) != 16);
781         BUILD_BUG_ON(sizeof(struct prestera_msg_ip_addr) != 20);
782         BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_port) != 12);
783         BUILD_BUG_ON(sizeof(struct prestera_msg_nh) != 28);
784
785         /* check responses */
786         BUILD_BUG_ON(sizeof(struct prestera_msg_common_resp) != 8);
787         BUILD_BUG_ON(sizeof(struct prestera_msg_switch_init_resp) != 24);
788         BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_resp) != 136);
789         BUILD_BUG_ON(sizeof(struct prestera_msg_port_stats_resp) != 248);
790         BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_resp) != 20);
791         BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_resp) != 12);
792         BUILD_BUG_ON(sizeof(struct prestera_msg_span_resp) != 12);
793         BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_resp) != 12);
794         BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_resp) != 16);
795         BUILD_BUG_ON(sizeof(struct prestera_msg_counter_resp) != 24);
796         BUILD_BUG_ON(sizeof(struct prestera_msg_rif_resp) != 12);
797         BUILD_BUG_ON(sizeof(struct prestera_msg_vr_resp) != 12);
798         BUILD_BUG_ON(sizeof(struct prestera_msg_policer_resp) != 12);
799         BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_create_resp) != 12);
800         BUILD_BUG_ON(sizeof(struct prestera_msg_nh_chunk_resp) != 1032);
801         BUILD_BUG_ON(sizeof(struct prestera_msg_nh_grp_resp) != 12);
802
803         /* check events */
804         BUILD_BUG_ON(sizeof(struct prestera_msg_event_port) != 20);
805         BUILD_BUG_ON(sizeof(struct prestera_msg_event_fdb) != 20);
806 }
807
808 static u8 prestera_hw_mdix_to_eth(u8 mode);
809 static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause);
810
811 static int __prestera_cmd_ret(struct prestera_switch *sw,
812                               enum prestera_cmd_type_t type,
813                               struct prestera_msg_cmd *cmd, size_t clen,
814                               struct prestera_msg_ret *ret, size_t rlen,
815                               int waitms)
816 {
817         struct prestera_device *dev = sw->dev;
818         int err;
819
820         cmd->type = __cpu_to_le32(type);
821
822         err = dev->send_req(dev, 0, cmd, clen, ret, rlen, waitms);
823         if (err)
824                 return err;
825
826         if (ret->cmd.type != __cpu_to_le32(PRESTERA_CMD_TYPE_ACK))
827                 return -EBADE;
828         if (ret->status != __cpu_to_le32(PRESTERA_CMD_ACK_OK))
829                 return -EINVAL;
830
831         return 0;
832 }
833
834 static int prestera_cmd_ret(struct prestera_switch *sw,
835                             enum prestera_cmd_type_t type,
836                             struct prestera_msg_cmd *cmd, size_t clen,
837                             struct prestera_msg_ret *ret, size_t rlen)
838 {
839         return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0);
840 }
841
842 static int prestera_cmd_ret_wait(struct prestera_switch *sw,
843                                  enum prestera_cmd_type_t type,
844                                  struct prestera_msg_cmd *cmd, size_t clen,
845                                  struct prestera_msg_ret *ret, size_t rlen,
846                                  int waitms)
847 {
848         return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms);
849 }
850
851 static int prestera_cmd(struct prestera_switch *sw,
852                         enum prestera_cmd_type_t type,
853                         struct prestera_msg_cmd *cmd, size_t clen)
854 {
855         struct prestera_msg_common_resp resp;
856
857         return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp));
858 }
859
860 static int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt)
861 {
862         struct prestera_msg_event_port *hw_evt;
863
864         hw_evt = (struct prestera_msg_event_port *)msg;
865
866         evt->port_evt.port_id = __le32_to_cpu(hw_evt->port_id);
867
868         if (evt->id == PRESTERA_PORT_EVENT_MAC_STATE_CHANGED) {
869                 evt->port_evt.data.mac.oper = hw_evt->param.mac.oper;
870                 evt->port_evt.data.mac.mode =
871                         __le32_to_cpu(hw_evt->param.mac.mode);
872                 evt->port_evt.data.mac.speed =
873                         __le32_to_cpu(hw_evt->param.mac.speed);
874                 evt->port_evt.data.mac.duplex = hw_evt->param.mac.duplex;
875                 evt->port_evt.data.mac.fc = hw_evt->param.mac.fc;
876                 evt->port_evt.data.mac.fec = hw_evt->param.mac.fec;
877         } else {
878                 return -EINVAL;
879         }
880
881         return 0;
882 }
883
884 static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt)
885 {
886         struct prestera_msg_event_fdb *hw_evt = msg;
887
888         switch (hw_evt->dest_type) {
889         case PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT:
890                 evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_REG_PORT;
891                 evt->fdb_evt.dest.port_id = __le32_to_cpu(hw_evt->dest.port_id);
892                 break;
893         case PRESTERA_HW_FDB_ENTRY_TYPE_LAG:
894                 evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_LAG;
895                 evt->fdb_evt.dest.lag_id = __le16_to_cpu(hw_evt->dest.lag_id);
896                 break;
897         default:
898                 return -EINVAL;
899         }
900
901         evt->fdb_evt.vid = __le32_to_cpu(hw_evt->vid);
902
903         ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac);
904
905         return 0;
906 }
907
908 static struct prestera_fw_evt_parser {
909         int (*func)(void *msg, struct prestera_event *evt);
910 } fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = {
911         [PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt },
912         [PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt },
913 };
914
915 static struct prestera_fw_event_handler *
916 __find_event_handler(const struct prestera_switch *sw,
917                      enum prestera_event_type type)
918 {
919         struct prestera_fw_event_handler *eh;
920
921         list_for_each_entry_rcu(eh, &sw->event_handlers, list) {
922                 if (eh->type == type)
923                         return eh;
924         }
925
926         return NULL;
927 }
928
929 static int prestera_find_event_handler(const struct prestera_switch *sw,
930                                        enum prestera_event_type type,
931                                        struct prestera_fw_event_handler *eh)
932 {
933         struct prestera_fw_event_handler *tmp;
934         int err = 0;
935
936         rcu_read_lock();
937         tmp = __find_event_handler(sw, type);
938         if (tmp)
939                 *eh = *tmp;
940         else
941                 err = -ENOENT;
942         rcu_read_unlock();
943
944         return err;
945 }
946
947 static int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size)
948 {
949         struct prestera_switch *sw = dev->priv;
950         struct prestera_msg_event *msg = buf;
951         struct prestera_fw_event_handler eh;
952         struct prestera_event evt;
953         u16 msg_type;
954         int err;
955
956         msg_type = __le16_to_cpu(msg->type);
957         if (msg_type >= PRESTERA_EVENT_TYPE_MAX)
958                 return -EINVAL;
959         if (!fw_event_parsers[msg_type].func)
960                 return -ENOENT;
961
962         err = prestera_find_event_handler(sw, msg_type, &eh);
963         if (err)
964                 return err;
965
966         evt.id = __le16_to_cpu(msg->id);
967
968         err = fw_event_parsers[msg_type].func(buf, &evt);
969         if (err)
970                 return err;
971
972         eh.func(sw, &evt, eh.arg);
973
974         return 0;
975 }
976
977 static void prestera_pkt_recv(struct prestera_device *dev)
978 {
979         struct prestera_switch *sw = dev->priv;
980         struct prestera_fw_event_handler eh;
981         struct prestera_event ev;
982         int err;
983
984         ev.id = PRESTERA_RXTX_EVENT_RCV_PKT;
985
986         err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh);
987         if (err)
988                 return;
989
990         eh.func(sw, &ev, eh.arg);
991 }
992
993 static u8 prestera_hw_mdix_to_eth(u8 mode)
994 {
995         switch (mode) {
996         case PRESTERA_PORT_TP_MDI:
997                 return ETH_TP_MDI;
998         case PRESTERA_PORT_TP_MDIX:
999                 return ETH_TP_MDI_X;
1000         case PRESTERA_PORT_TP_AUTO:
1001                 return ETH_TP_MDI_AUTO;
1002         default:
1003                 return ETH_TP_MDI_INVALID;
1004         }
1005 }
1006
1007 static u8 prestera_hw_mdix_from_eth(u8 mode)
1008 {
1009         switch (mode) {
1010         case ETH_TP_MDI:
1011                 return PRESTERA_PORT_TP_MDI;
1012         case ETH_TP_MDI_X:
1013                 return PRESTERA_PORT_TP_MDIX;
1014         case ETH_TP_MDI_AUTO:
1015                 return PRESTERA_PORT_TP_AUTO;
1016         default:
1017                 return PRESTERA_PORT_TP_NA;
1018         }
1019 }
1020
1021 int prestera_hw_port_info_get(const struct prestera_port *port,
1022                               u32 *dev_id, u32 *hw_id, u16 *fp_id)
1023 {
1024         struct prestera_msg_port_info_req req = {
1025                 .port = __cpu_to_le32(port->id),
1026         };
1027         struct prestera_msg_port_info_resp resp;
1028         int err;
1029
1030         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET,
1031                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1032         if (err)
1033                 return err;
1034
1035         *dev_id = __le32_to_cpu(resp.dev_id);
1036         *hw_id = __le32_to_cpu(resp.hw_id);
1037         *fp_id = __le16_to_cpu(resp.fp_id);
1038
1039         return 0;
1040 }
1041
1042 int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac)
1043 {
1044         struct prestera_msg_switch_attr_req req = {
1045                 .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_MAC),
1046         };
1047
1048         ether_addr_copy(req.param.mac, mac);
1049
1050         return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
1051                             &req.cmd, sizeof(req));
1052 }
1053
1054 int prestera_hw_switch_init(struct prestera_switch *sw)
1055 {
1056         struct prestera_msg_switch_init_resp resp;
1057         struct prestera_msg_common_req req;
1058         int err;
1059
1060         INIT_LIST_HEAD(&sw->event_handlers);
1061
1062         prestera_hw_build_tests();
1063
1064         err = prestera_cmd_ret_wait(sw, PRESTERA_CMD_TYPE_SWITCH_INIT,
1065                                     &req.cmd, sizeof(req),
1066                                     &resp.ret, sizeof(resp),
1067                                     PRESTERA_SWITCH_INIT_TIMEOUT_MS);
1068         if (err)
1069                 return err;
1070
1071         sw->dev->recv_msg = prestera_evt_recv;
1072         sw->dev->recv_pkt = prestera_pkt_recv;
1073         sw->port_count = __le32_to_cpu(resp.port_count);
1074         sw->mtu_min = PRESTERA_MIN_MTU;
1075         sw->mtu_max = __le32_to_cpu(resp.mtu_max);
1076         sw->id = resp.switch_id;
1077         sw->lag_member_max = resp.lag_member_max;
1078         sw->lag_max = resp.lag_max;
1079         sw->size_tbl_router_nexthop =
1080                 __le32_to_cpu(resp.size_tbl_router_nexthop);
1081
1082         return 0;
1083 }
1084
1085 void prestera_hw_switch_fini(struct prestera_switch *sw)
1086 {
1087         WARN_ON(!list_empty(&sw->event_handlers));
1088 }
1089
1090 int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms)
1091 {
1092         struct prestera_msg_switch_attr_req req = {
1093                 .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_AGEING),
1094                 .param = {
1095                         .ageing_timeout_ms = __cpu_to_le32(ageing_ms),
1096                 },
1097         };
1098
1099         return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
1100                             &req.cmd, sizeof(req));
1101 }
1102
1103 int prestera_hw_port_mac_mode_get(const struct prestera_port *port,
1104                                   u32 *mode, u32 *speed, u8 *duplex, u8 *fec)
1105 {
1106         struct prestera_msg_port_attr_resp resp;
1107         struct prestera_msg_port_attr_req req = {
1108                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
1109                 .port = __cpu_to_le32(port->hw_id),
1110                 .dev = __cpu_to_le32(port->dev_id)
1111         };
1112         int err;
1113
1114         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1115                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1116         if (err)
1117                 return err;
1118
1119         if (mode)
1120                 *mode = __le32_to_cpu(resp.param.link_evt.mac.mode);
1121
1122         if (speed)
1123                 *speed = __le32_to_cpu(resp.param.link_evt.mac.speed);
1124
1125         if (duplex)
1126                 *duplex = resp.param.link_evt.mac.duplex;
1127
1128         if (fec)
1129                 *fec = resp.param.link_evt.mac.fec;
1130
1131         return err;
1132 }
1133
1134 int prestera_hw_port_mac_mode_set(const struct prestera_port *port,
1135                                   bool admin, u32 mode, u8 inband,
1136                                   u32 speed, u8 duplex, u8 fec)
1137 {
1138         struct prestera_msg_port_attr_req req = {
1139                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
1140                 .port = __cpu_to_le32(port->hw_id),
1141                 .dev = __cpu_to_le32(port->dev_id),
1142                 .param = {
1143                         .link = {
1144                                 .mac = {
1145                                         .admin = admin,
1146                                         .reg_mode.mode = __cpu_to_le32(mode),
1147                                         .reg_mode.inband = inband,
1148                                         .reg_mode.speed = __cpu_to_le32(speed),
1149                                         .reg_mode.duplex = duplex,
1150                                         .reg_mode.fec = fec
1151                                 }
1152                         }
1153                 }
1154         };
1155
1156         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1157                             &req.cmd, sizeof(req));
1158 }
1159
1160 int prestera_hw_port_phy_mode_get(const struct prestera_port *port,
1161                                   u8 *mdix, u64 *lmode_bmap,
1162                                   bool *fc_pause, bool *fc_asym)
1163 {
1164         struct prestera_msg_port_attr_resp resp;
1165         struct prestera_msg_port_attr_req req = {
1166                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_MODE),
1167                 .port = __cpu_to_le32(port->hw_id),
1168                 .dev = __cpu_to_le32(port->dev_id)
1169         };
1170         int err;
1171
1172         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1173                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1174         if (err)
1175                 return err;
1176
1177         if (mdix)
1178                 *mdix = prestera_hw_mdix_to_eth(resp.param.link_evt.phy.mdix);
1179
1180         if (lmode_bmap)
1181                 *lmode_bmap = __le64_to_cpu(resp.param.link_evt.phy.lmode_bmap);
1182
1183         if (fc_pause && fc_asym)
1184                 prestera_hw_remote_fc_to_eth(resp.param.link_evt.phy.fc,
1185                                              fc_pause, fc_asym);
1186
1187         return err;
1188 }
1189
1190 int prestera_hw_port_phy_mode_set(const struct prestera_port *port,
1191                                   bool admin, bool adv, u32 mode, u64 modes,
1192                                   u8 mdix)
1193 {
1194         struct prestera_msg_port_attr_req req = {
1195                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_MODE),
1196                 .port = __cpu_to_le32(port->hw_id),
1197                 .dev = __cpu_to_le32(port->dev_id),
1198                 .param = {
1199                         .link = {
1200                                 .phy = {
1201                                         .admin = admin,
1202                                         .adv_enable = adv ? 1 : 0,
1203                                         .mode = __cpu_to_le32(mode),
1204                                         .modes = __cpu_to_le64(modes),
1205                                 }
1206                         }
1207                 }
1208         };
1209
1210         req.param.link.phy.mdix = prestera_hw_mdix_from_eth(mdix);
1211
1212         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1213                             &req.cmd, sizeof(req));
1214 }
1215
1216 int prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu)
1217 {
1218         struct prestera_msg_port_attr_req req = {
1219                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MTU),
1220                 .port = __cpu_to_le32(port->hw_id),
1221                 .dev = __cpu_to_le32(port->dev_id),
1222                 .param = {
1223                         .mtu = __cpu_to_le32(mtu),
1224                 }
1225         };
1226
1227         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1228                             &req.cmd, sizeof(req));
1229 }
1230
1231 int prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac)
1232 {
1233         struct prestera_msg_port_attr_req req = {
1234                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC),
1235                 .port = __cpu_to_le32(port->hw_id),
1236                 .dev = __cpu_to_le32(port->dev_id),
1237         };
1238
1239         ether_addr_copy(req.param.mac, mac);
1240
1241         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1242                             &req.cmd, sizeof(req));
1243 }
1244
1245 int prestera_hw_port_accept_frm_type(struct prestera_port *port,
1246                                      enum prestera_accept_frm_type type)
1247 {
1248         struct prestera_msg_port_attr_req req = {
1249                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE),
1250                 .port = __cpu_to_le32(port->hw_id),
1251                 .dev = __cpu_to_le32(port->dev_id),
1252                 .param = {
1253                         .accept_frm_type = type,
1254                 }
1255         };
1256
1257         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1258                             &req.cmd, sizeof(req));
1259 }
1260
1261 int prestera_hw_port_cap_get(const struct prestera_port *port,
1262                              struct prestera_port_caps *caps)
1263 {
1264         struct prestera_msg_port_attr_req req = {
1265                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_CAPABILITY),
1266                 .port = __cpu_to_le32(port->hw_id),
1267                 .dev = __cpu_to_le32(port->dev_id),
1268         };
1269         struct prestera_msg_port_attr_resp resp;
1270         int err;
1271
1272         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1273                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1274         if (err)
1275                 return err;
1276
1277         caps->supp_link_modes = __le64_to_cpu(resp.param.cap.link_mode);
1278         caps->transceiver = resp.param.cap.transceiver;
1279         caps->supp_fec = resp.param.cap.fec;
1280         caps->type = resp.param.cap.type;
1281
1282         return err;
1283 }
1284
1285 static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause)
1286 {
1287         switch (fc) {
1288         case PRESTERA_FC_SYMMETRIC:
1289                 *pause = true;
1290                 *asym_pause = false;
1291                 break;
1292         case PRESTERA_FC_ASYMMETRIC:
1293                 *pause = false;
1294                 *asym_pause = true;
1295                 break;
1296         case PRESTERA_FC_SYMM_ASYMM:
1297                 *pause = true;
1298                 *asym_pause = true;
1299                 break;
1300         default:
1301                 *pause = false;
1302                 *asym_pause = false;
1303         }
1304 }
1305
1306 int prestera_hw_vtcam_create(struct prestera_switch *sw,
1307                              u8 lookup, const u32 *keymask, u32 *vtcam_id,
1308                              enum prestera_hw_vtcam_direction_t dir)
1309 {
1310         int err;
1311         struct prestera_msg_vtcam_resp resp;
1312         struct prestera_msg_vtcam_create_req req = {
1313                 .lookup = lookup,
1314                 .direction = dir,
1315         };
1316
1317         if (keymask)
1318                 memcpy(req.keymask, keymask, sizeof(req.keymask));
1319         else
1320                 memset(req.keymask, 0, sizeof(req.keymask));
1321
1322         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_CREATE,
1323                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1324         if (err)
1325                 return err;
1326
1327         *vtcam_id = __le32_to_cpu(resp.vtcam_id);
1328         return 0;
1329 }
1330
1331 int prestera_hw_vtcam_destroy(struct prestera_switch *sw, u32 vtcam_id)
1332 {
1333         struct prestera_msg_vtcam_destroy_req req = {
1334                 .vtcam_id = __cpu_to_le32(vtcam_id),
1335         };
1336
1337         return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_DESTROY,
1338                             &req.cmd, sizeof(req));
1339 }
1340
1341 static int
1342 prestera_acl_rule_add_put_action(struct prestera_msg_acl_action *action,
1343                                  struct prestera_acl_hw_action_info *info)
1344 {
1345         action->id = __cpu_to_le32(info->id);
1346
1347         switch (info->id) {
1348         case PRESTERA_ACL_RULE_ACTION_ACCEPT:
1349         case PRESTERA_ACL_RULE_ACTION_DROP:
1350         case PRESTERA_ACL_RULE_ACTION_TRAP:
1351                 /* just rule action id, no specific data */
1352                 break;
1353         case PRESTERA_ACL_RULE_ACTION_JUMP:
1354                 action->jump.index = __cpu_to_le32(info->jump.index);
1355                 break;
1356         case PRESTERA_ACL_RULE_ACTION_POLICE:
1357                 action->police.id = __cpu_to_le32(info->police.id);
1358                 break;
1359         case PRESTERA_ACL_RULE_ACTION_COUNT:
1360                 action->count.id = __cpu_to_le32(info->count.id);
1361                 break;
1362         default:
1363                 return -EINVAL;
1364         }
1365
1366         return 0;
1367 }
1368
1369 int prestera_hw_vtcam_rule_add(struct prestera_switch *sw,
1370                                u32 vtcam_id, u32 prio, void *key, void *keymask,
1371                                struct prestera_acl_hw_action_info *act,
1372                                u8 n_act, u32 *rule_id)
1373 {
1374         struct prestera_msg_acl_action *actions_msg;
1375         struct prestera_msg_vtcam_rule_add_req *req;
1376         struct prestera_msg_vtcam_resp resp;
1377         void *buff;
1378         u32 size;
1379         int err;
1380         u8 i;
1381
1382         size = sizeof(*req) + sizeof(*actions_msg) * n_act;
1383
1384         buff = kzalloc(size, GFP_KERNEL);
1385         if (!buff)
1386                 return -ENOMEM;
1387
1388         req = buff;
1389         req->n_act = __cpu_to_le32(n_act);
1390         actions_msg = buff + sizeof(*req);
1391
1392         /* put acl matches into the message */
1393         memcpy(req->key, key, sizeof(req->key));
1394         memcpy(req->keymask, keymask, sizeof(req->keymask));
1395
1396         /* put acl actions into the message */
1397         for (i = 0; i < n_act; i++) {
1398                 err = prestera_acl_rule_add_put_action(&actions_msg[i],
1399                                                        &act[i]);
1400                 if (err)
1401                         goto free_buff;
1402         }
1403
1404         req->vtcam_id = __cpu_to_le32(vtcam_id);
1405         req->prio = __cpu_to_le32(prio);
1406
1407         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_ADD,
1408                                &req->cmd, size, &resp.ret, sizeof(resp));
1409         if (err)
1410                 goto free_buff;
1411
1412         *rule_id = __le32_to_cpu(resp.rule_id);
1413 free_buff:
1414         kfree(buff);
1415         return err;
1416 }
1417
1418 int prestera_hw_vtcam_rule_del(struct prestera_switch *sw,
1419                                u32 vtcam_id, u32 rule_id)
1420 {
1421         struct prestera_msg_vtcam_rule_del_req req = {
1422                 .vtcam_id = __cpu_to_le32(vtcam_id),
1423                 .id = __cpu_to_le32(rule_id)
1424         };
1425
1426         return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_DELETE,
1427                             &req.cmd, sizeof(req));
1428 }
1429
1430 int prestera_hw_vtcam_iface_bind(struct prestera_switch *sw,
1431                                  struct prestera_acl_iface *iface,
1432                                  u32 vtcam_id, u16 pcl_id)
1433 {
1434         struct prestera_msg_vtcam_bind_req req = {
1435                 .vtcam_id = __cpu_to_le32(vtcam_id),
1436                 .type = __cpu_to_le16(iface->type),
1437                 .pcl_id = __cpu_to_le16(pcl_id)
1438         };
1439
1440         if (iface->type == PRESTERA_ACL_IFACE_TYPE_PORT) {
1441                 req.port.dev_id = __cpu_to_le32(iface->port->dev_id);
1442                 req.port.hw_id = __cpu_to_le32(iface->port->hw_id);
1443         } else {
1444                 req.index = __cpu_to_le32(iface->index);
1445         }
1446
1447         return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_BIND,
1448                             &req.cmd, sizeof(req));
1449 }
1450
1451 int prestera_hw_vtcam_iface_unbind(struct prestera_switch *sw,
1452                                    struct prestera_acl_iface *iface,
1453                                    u32 vtcam_id)
1454 {
1455         struct prestera_msg_vtcam_bind_req req = {
1456                 .vtcam_id = __cpu_to_le32(vtcam_id),
1457                 .type = __cpu_to_le16(iface->type)
1458         };
1459
1460         if (iface->type == PRESTERA_ACL_IFACE_TYPE_PORT) {
1461                 req.port.dev_id = __cpu_to_le32(iface->port->dev_id);
1462                 req.port.hw_id = __cpu_to_le32(iface->port->hw_id);
1463         } else {
1464                 req.index = __cpu_to_le32(iface->index);
1465         }
1466
1467         return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_UNBIND,
1468                             &req.cmd, sizeof(req));
1469 }
1470
1471 int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id)
1472 {
1473         struct prestera_msg_span_resp resp;
1474         struct prestera_msg_span_req req = {
1475                 .port = __cpu_to_le32(port->hw_id),
1476                 .dev = __cpu_to_le32(port->dev_id),
1477         };
1478         int err;
1479
1480         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_SPAN_GET,
1481                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1482         if (err)
1483                 return err;
1484
1485         *span_id = resp.id;
1486
1487         return 0;
1488 }
1489
1490 int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id,
1491                           bool ingress)
1492 {
1493         struct prestera_msg_span_req req = {
1494                 .port = __cpu_to_le32(port->hw_id),
1495                 .dev = __cpu_to_le32(port->dev_id),
1496                 .id = span_id,
1497         };
1498         enum prestera_cmd_type_t cmd_type;
1499
1500         if (ingress)
1501                 cmd_type = PRESTERA_CMD_TYPE_SPAN_INGRESS_BIND;
1502         else
1503                 cmd_type = PRESTERA_CMD_TYPE_SPAN_EGRESS_BIND;
1504
1505         return prestera_cmd(port->sw, cmd_type, &req.cmd, sizeof(req));
1506
1507 }
1508
1509 int prestera_hw_span_unbind(const struct prestera_port *port, bool ingress)
1510 {
1511         struct prestera_msg_span_req req = {
1512                 .port = __cpu_to_le32(port->hw_id),
1513                 .dev = __cpu_to_le32(port->dev_id),
1514         };
1515         enum prestera_cmd_type_t cmd_type;
1516
1517         if (ingress)
1518                 cmd_type = PRESTERA_CMD_TYPE_SPAN_INGRESS_UNBIND;
1519         else
1520                 cmd_type = PRESTERA_CMD_TYPE_SPAN_EGRESS_UNBIND;
1521
1522         return prestera_cmd(port->sw, cmd_type, &req.cmd, sizeof(req));
1523 }
1524
1525 int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id)
1526 {
1527         struct prestera_msg_span_req req = {
1528                 .id = span_id
1529         };
1530
1531         return prestera_cmd(sw, PRESTERA_CMD_TYPE_SPAN_RELEASE,
1532                             &req.cmd, sizeof(req));
1533 }
1534
1535 int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
1536 {
1537         struct prestera_msg_port_attr_req req = {
1538                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_TYPE),
1539                 .port = __cpu_to_le32(port->hw_id),
1540                 .dev = __cpu_to_le32(port->dev_id),
1541         };
1542         struct prestera_msg_port_attr_resp resp;
1543         int err;
1544
1545         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1546                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1547         if (err)
1548                 return err;
1549
1550         *type = resp.param.type;
1551
1552         return 0;
1553 }
1554
1555 int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed)
1556 {
1557         struct prestera_msg_port_attr_req req = {
1558                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_SPEED),
1559                 .port = __cpu_to_le32(port->hw_id),
1560                 .dev = __cpu_to_le32(port->dev_id),
1561         };
1562         struct prestera_msg_port_attr_resp resp;
1563         int err;
1564
1565         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1566                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1567         if (err)
1568                 return err;
1569
1570         *speed = __le32_to_cpu(resp.param.speed);
1571
1572         return 0;
1573 }
1574
1575 int prestera_hw_port_autoneg_restart(struct prestera_port *port)
1576 {
1577         struct prestera_msg_port_attr_req req = {
1578                 .attr =
1579                     __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART),
1580                 .port = __cpu_to_le32(port->hw_id),
1581                 .dev = __cpu_to_le32(port->dev_id),
1582         };
1583
1584         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1585                             &req.cmd, sizeof(req));
1586 }
1587
1588 int prestera_hw_port_stats_get(const struct prestera_port *port,
1589                                struct prestera_port_stats *st)
1590 {
1591         struct prestera_msg_port_attr_req req = {
1592                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_STATS),
1593                 .port = __cpu_to_le32(port->hw_id),
1594                 .dev = __cpu_to_le32(port->dev_id),
1595         };
1596         struct prestera_msg_port_stats_resp resp;
1597         __le64 *hw = resp.stats;
1598         int err;
1599
1600         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1601                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1602         if (err)
1603                 return err;
1604
1605         st->good_octets_received =
1606                 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_RCV_CNT]);
1607         st->bad_octets_received =
1608                 __le64_to_cpu(hw[PRESTERA_PORT_BAD_OCTETS_RCV_CNT]);
1609         st->mac_trans_error =
1610                 __le64_to_cpu(hw[PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT]);
1611         st->broadcast_frames_received =
1612                 __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_RCV_CNT]);
1613         st->multicast_frames_received =
1614                 __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_RCV_CNT]);
1615         st->frames_64_octets = __le64_to_cpu(hw[PRESTERA_PORT_PKTS_64L_CNT]);
1616         st->frames_65_to_127_octets =
1617                 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_65TO127L_CNT]);
1618         st->frames_128_to_255_octets =
1619                 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_128TO255L_CNT]);
1620         st->frames_256_to_511_octets =
1621                 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_256TO511L_CNT]);
1622         st->frames_512_to_1023_octets =
1623                 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_512TO1023L_CNT]);
1624         st->frames_1024_to_max_octets =
1625                 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_1024TOMAXL_CNT]);
1626         st->excessive_collision =
1627                 __le64_to_cpu(hw[PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT]);
1628         st->multicast_frames_sent =
1629                 __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_SENT_CNT]);
1630         st->broadcast_frames_sent =
1631                 __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_SENT_CNT]);
1632         st->fc_sent = __le64_to_cpu(hw[PRESTERA_PORT_FC_SENT_CNT]);
1633         st->fc_received = __le64_to_cpu(hw[PRESTERA_PORT_GOOD_FC_RCV_CNT]);
1634         st->buffer_overrun = __le64_to_cpu(hw[PRESTERA_PORT_DROP_EVENTS_CNT]);
1635         st->undersize = __le64_to_cpu(hw[PRESTERA_PORT_UNDERSIZE_PKTS_CNT]);
1636         st->fragments = __le64_to_cpu(hw[PRESTERA_PORT_FRAGMENTS_PKTS_CNT]);
1637         st->oversize = __le64_to_cpu(hw[PRESTERA_PORT_OVERSIZE_PKTS_CNT]);
1638         st->jabber = __le64_to_cpu(hw[PRESTERA_PORT_JABBER_PKTS_CNT]);
1639         st->rx_error_frame_received =
1640                 __le64_to_cpu(hw[PRESTERA_PORT_MAC_RCV_ERROR_CNT]);
1641         st->bad_crc = __le64_to_cpu(hw[PRESTERA_PORT_BAD_CRC_CNT]);
1642         st->collisions = __le64_to_cpu(hw[PRESTERA_PORT_COLLISIONS_CNT]);
1643         st->late_collision =
1644                 __le64_to_cpu(hw[PRESTERA_PORT_LATE_COLLISIONS_CNT]);
1645         st->unicast_frames_received =
1646                 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT]);
1647         st->unicast_frames_sent =
1648                 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT]);
1649         st->sent_multiple =
1650                 __le64_to_cpu(hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT]);
1651         st->sent_deferred =
1652                 __le64_to_cpu(hw[PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT]);
1653         st->good_octets_sent =
1654                 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT]);
1655
1656         return 0;
1657 }
1658
1659 int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
1660 {
1661         struct prestera_msg_port_attr_req req = {
1662                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_LEARNING),
1663                 .port = __cpu_to_le32(port->hw_id),
1664                 .dev = __cpu_to_le32(port->dev_id),
1665                 .param = {
1666                         .learning = enable,
1667                 }
1668         };
1669
1670         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1671                             &req.cmd, sizeof(req));
1672 }
1673
1674 int prestera_hw_port_uc_flood_set(const struct prestera_port *port, bool flood)
1675 {
1676         struct prestera_msg_port_attr_req req = {
1677                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1678                 .port = __cpu_to_le32(port->hw_id),
1679                 .dev = __cpu_to_le32(port->dev_id),
1680                 .param = {
1681                         .flood_ext = {
1682                                 .type = PRESTERA_PORT_FLOOD_TYPE_UC,
1683                                 .enable = flood,
1684                         }
1685                 }
1686         };
1687
1688         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1689                             &req.cmd, sizeof(req));
1690 }
1691
1692 int prestera_hw_port_mc_flood_set(const struct prestera_port *port, bool flood)
1693 {
1694         struct prestera_msg_port_attr_req req = {
1695                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1696                 .port = __cpu_to_le32(port->hw_id),
1697                 .dev = __cpu_to_le32(port->dev_id),
1698                 .param = {
1699                         .flood_ext = {
1700                                 .type = PRESTERA_PORT_FLOOD_TYPE_MC,
1701                                 .enable = flood,
1702                         }
1703                 }
1704         };
1705
1706         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1707                             &req.cmd, sizeof(req));
1708 }
1709
1710 int prestera_hw_port_br_locked_set(const struct prestera_port *port,
1711                                    bool br_locked)
1712 {
1713         struct prestera_msg_port_attr_req req = {
1714                 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_LOCKED),
1715                 .port = __cpu_to_le32(port->hw_id),
1716                 .dev = __cpu_to_le32(port->dev_id),
1717                 .param = {
1718                         .br_locked = br_locked,
1719                 }
1720         };
1721
1722         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1723                             &req.cmd, sizeof(req));
1724 }
1725
1726 int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
1727 {
1728         struct prestera_msg_vlan_req req = {
1729                 .vid = __cpu_to_le16(vid),
1730         };
1731
1732         return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE,
1733                             &req.cmd, sizeof(req));
1734 }
1735
1736 int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid)
1737 {
1738         struct prestera_msg_vlan_req req = {
1739                 .vid = __cpu_to_le16(vid),
1740         };
1741
1742         return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE,
1743                             &req.cmd, sizeof(req));
1744 }
1745
1746 int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid,
1747                               bool is_member, bool untagged)
1748 {
1749         struct prestera_msg_vlan_req req = {
1750                 .port = __cpu_to_le32(port->hw_id),
1751                 .dev = __cpu_to_le32(port->dev_id),
1752                 .vid = __cpu_to_le16(vid),
1753                 .is_member = is_member,
1754                 .is_tagged = !untagged,
1755         };
1756
1757         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET,
1758                             &req.cmd, sizeof(req));
1759 }
1760
1761 int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid)
1762 {
1763         struct prestera_msg_vlan_req req = {
1764                 .port = __cpu_to_le32(port->hw_id),
1765                 .dev = __cpu_to_le32(port->dev_id),
1766                 .vid = __cpu_to_le16(vid),
1767         };
1768
1769         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET,
1770                             &req.cmd, sizeof(req));
1771 }
1772
1773 int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state)
1774 {
1775         struct prestera_msg_stp_req req = {
1776                 .port = __cpu_to_le32(port->hw_id),
1777                 .dev = __cpu_to_le32(port->dev_id),
1778                 .vid = __cpu_to_le16(vid),
1779                 .state = state,
1780         };
1781
1782         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET,
1783                             &req.cmd, sizeof(req));
1784 }
1785
1786 int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac,
1787                         u16 vid, bool dynamic)
1788 {
1789         struct prestera_msg_fdb_req req = {
1790                 .dest = {
1791                         .dev = __cpu_to_le32(port->dev_id),
1792                         .port = __cpu_to_le32(port->hw_id),
1793                 },
1794                 .vid = __cpu_to_le16(vid),
1795                 .dynamic = dynamic,
1796         };
1797
1798         ether_addr_copy(req.mac, mac);
1799
1800         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD,
1801                             &req.cmd, sizeof(req));
1802 }
1803
1804 int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac,
1805                         u16 vid)
1806 {
1807         struct prestera_msg_fdb_req req = {
1808                 .dest = {
1809                         .dev = __cpu_to_le32(port->dev_id),
1810                         .port = __cpu_to_le32(port->hw_id),
1811                 },
1812                 .vid = __cpu_to_le16(vid),
1813         };
1814
1815         ether_addr_copy(req.mac, mac);
1816
1817         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1818                             &req.cmd, sizeof(req));
1819 }
1820
1821 int prestera_hw_lag_fdb_add(struct prestera_switch *sw, u16 lag_id,
1822                             const unsigned char *mac, u16 vid, bool dynamic)
1823 {
1824         struct prestera_msg_fdb_req req = {
1825                 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1826                 .dest = {
1827                         .lag_id = __cpu_to_le16(lag_id),
1828                 },
1829                 .vid = __cpu_to_le16(vid),
1830                 .dynamic = dynamic,
1831         };
1832
1833         ether_addr_copy(req.mac, mac);
1834
1835         return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_ADD,
1836                             &req.cmd, sizeof(req));
1837 }
1838
1839 int prestera_hw_lag_fdb_del(struct prestera_switch *sw, u16 lag_id,
1840                             const unsigned char *mac, u16 vid)
1841 {
1842         struct prestera_msg_fdb_req req = {
1843                 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1844                 .dest = {
1845                         .lag_id = __cpu_to_le16(lag_id),
1846                 },
1847                 .vid = __cpu_to_le16(vid),
1848         };
1849
1850         ether_addr_copy(req.mac, mac);
1851
1852         return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1853                             &req.cmd, sizeof(req));
1854 }
1855
1856 int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode)
1857 {
1858         struct prestera_msg_fdb_req req = {
1859                 .dest = {
1860                         .dev = __cpu_to_le32(port->dev_id),
1861                         .port = __cpu_to_le32(port->hw_id),
1862                 },
1863                 .flush_mode = __cpu_to_le32(mode),
1864         };
1865
1866         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1867                             &req.cmd, sizeof(req));
1868 }
1869
1870 int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode)
1871 {
1872         struct prestera_msg_fdb_req req = {
1873                 .vid = __cpu_to_le16(vid),
1874                 .flush_mode = __cpu_to_le32(mode),
1875         };
1876
1877         return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN,
1878                             &req.cmd, sizeof(req));
1879 }
1880
1881 int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
1882                                     u32 mode)
1883 {
1884         struct prestera_msg_fdb_req req = {
1885                 .dest = {
1886                         .dev = __cpu_to_le32(port->dev_id),
1887                         .port = __cpu_to_le32(port->hw_id),
1888                 },
1889                 .vid = __cpu_to_le16(vid),
1890                 .flush_mode = __cpu_to_le32(mode),
1891         };
1892
1893         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1894                             &req.cmd, sizeof(req));
1895 }
1896
1897 int prestera_hw_fdb_flush_lag(struct prestera_switch *sw, u16 lag_id,
1898                               u32 mode)
1899 {
1900         struct prestera_msg_fdb_req req = {
1901                 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1902                 .dest = {
1903                         .lag_id = __cpu_to_le16(lag_id),
1904                 },
1905                 .flush_mode = __cpu_to_le32(mode),
1906         };
1907
1908         return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1909                             &req.cmd, sizeof(req));
1910 }
1911
1912 int prestera_hw_fdb_flush_lag_vlan(struct prestera_switch *sw,
1913                                    u16 lag_id, u16 vid, u32 mode)
1914 {
1915         struct prestera_msg_fdb_req req = {
1916                 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1917                 .dest = {
1918                         .lag_id = __cpu_to_le16(lag_id),
1919                 },
1920                 .vid = __cpu_to_le16(vid),
1921                 .flush_mode = __cpu_to_le32(mode),
1922         };
1923
1924         return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1925                             &req.cmd, sizeof(req));
1926 }
1927
1928 int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id)
1929 {
1930         struct prestera_msg_bridge_resp resp;
1931         struct prestera_msg_bridge_req req;
1932         int err;
1933
1934         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE,
1935                                &req.cmd, sizeof(req),
1936                                &resp.ret, sizeof(resp));
1937         if (err)
1938                 return err;
1939
1940         *bridge_id = __le16_to_cpu(resp.bridge);
1941
1942         return 0;
1943 }
1944
1945 int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id)
1946 {
1947         struct prestera_msg_bridge_req req = {
1948                 .bridge = __cpu_to_le16(bridge_id),
1949         };
1950
1951         return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE,
1952                             &req.cmd, sizeof(req));
1953 }
1954
1955 int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id)
1956 {
1957         struct prestera_msg_bridge_req req = {
1958                 .bridge = __cpu_to_le16(bridge_id),
1959                 .port = __cpu_to_le32(port->hw_id),
1960                 .dev = __cpu_to_le32(port->dev_id),
1961         };
1962
1963         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD,
1964                             &req.cmd, sizeof(req));
1965 }
1966
1967 int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)
1968 {
1969         struct prestera_msg_bridge_req req = {
1970                 .bridge = __cpu_to_le16(bridge_id),
1971                 .port = __cpu_to_le32(port->hw_id),
1972                 .dev = __cpu_to_le32(port->dev_id),
1973         };
1974
1975         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE,
1976                             &req.cmd, sizeof(req));
1977 }
1978
1979 static int prestera_iface_to_msg(struct prestera_iface *iface,
1980                                  struct prestera_msg_iface *msg_if)
1981 {
1982         switch (iface->type) {
1983         case PRESTERA_IF_PORT_E:
1984         case PRESTERA_IF_VID_E:
1985                 msg_if->port = __cpu_to_le32(iface->dev_port.port_num);
1986                 msg_if->dev = __cpu_to_le32(iface->dev_port.hw_dev_num);
1987                 break;
1988         case PRESTERA_IF_LAG_E:
1989                 msg_if->lag_id = __cpu_to_le16(iface->lag_id);
1990                 break;
1991         default:
1992                 return -EOPNOTSUPP;
1993         }
1994
1995         msg_if->vr_id = __cpu_to_le16(iface->vr_id);
1996         msg_if->vid = __cpu_to_le16(iface->vlan_id);
1997         msg_if->type = iface->type;
1998         return 0;
1999 }
2000
2001 int prestera_hw_rif_create(struct prestera_switch *sw,
2002                            struct prestera_iface *iif, u8 *mac, u16 *rif_id)
2003 {
2004         struct prestera_msg_rif_resp resp;
2005         struct prestera_msg_rif_req req;
2006         int err;
2007
2008         memcpy(req.mac, mac, ETH_ALEN);
2009
2010         err = prestera_iface_to_msg(iif, &req.iif);
2011         if (err)
2012                 return err;
2013
2014         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_CREATE,
2015                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2016         if (err)
2017                 return err;
2018
2019         *rif_id = __le16_to_cpu(resp.rif_id);
2020         return err;
2021 }
2022
2023 int prestera_hw_rif_delete(struct prestera_switch *sw, u16 rif_id,
2024                            struct prestera_iface *iif)
2025 {
2026         struct prestera_msg_rif_req req = {
2027                 .rif_id = __cpu_to_le16(rif_id),
2028         };
2029         int err;
2030
2031         err = prestera_iface_to_msg(iif, &req.iif);
2032         if (err)
2033                 return err;
2034
2035         return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE, &req.cmd,
2036                             sizeof(req));
2037 }
2038
2039 int prestera_hw_vr_create(struct prestera_switch *sw, u16 *vr_id)
2040 {
2041         struct prestera_msg_vr_resp resp;
2042         struct prestera_msg_vr_req req;
2043         int err;
2044
2045         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_VR_CREATE,
2046                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2047         if (err)
2048                 return err;
2049
2050         *vr_id = __le16_to_cpu(resp.vr_id);
2051         return err;
2052 }
2053
2054 int prestera_hw_vr_delete(struct prestera_switch *sw, u16 vr_id)
2055 {
2056         struct prestera_msg_vr_req req = {
2057                 .vr_id = __cpu_to_le16(vr_id),
2058         };
2059
2060         return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_VR_DELETE, &req.cmd,
2061                             sizeof(req));
2062 }
2063
2064 int prestera_hw_lpm_add(struct prestera_switch *sw, u16 vr_id,
2065                         __be32 dst, u32 dst_len, u32 grp_id)
2066 {
2067         struct prestera_msg_lpm_req req = {
2068                 .dst_len = __cpu_to_le32(dst_len),
2069                 .vr_id = __cpu_to_le16(vr_id),
2070                 .grp_id = __cpu_to_le32(grp_id),
2071                 .dst.u.ipv4 = dst
2072         };
2073
2074         return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_ADD, &req.cmd,
2075                             sizeof(req));
2076 }
2077
2078 int prestera_hw_lpm_del(struct prestera_switch *sw, u16 vr_id,
2079                         __be32 dst, u32 dst_len)
2080 {
2081         struct prestera_msg_lpm_req req = {
2082                 .dst_len = __cpu_to_le32(dst_len),
2083                 .vr_id = __cpu_to_le16(vr_id),
2084                 .dst.u.ipv4 = dst
2085         };
2086
2087         return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_DELETE, &req.cmd,
2088                             sizeof(req));
2089 }
2090
2091 int prestera_hw_nh_entries_set(struct prestera_switch *sw, int count,
2092                                struct prestera_neigh_info *nhs, u32 grp_id)
2093 {
2094         struct prestera_msg_nh_req req = { .size = __cpu_to_le32((u32)count),
2095                         .grp_id = __cpu_to_le32(grp_id) };
2096         int i, err;
2097
2098         for (i = 0; i < count; i++) {
2099                 req.nh[i].is_active = nhs[i].connected;
2100                 memcpy(&req.nh[i].mac, nhs[i].ha, ETH_ALEN);
2101                 err = prestera_iface_to_msg(&nhs[i].iface, &req.nh[i].oif);
2102                 if (err)
2103                         return err;
2104         }
2105
2106         return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_NH_GRP_SET, &req.cmd,
2107                             sizeof(req));
2108 }
2109
2110 int prestera_hw_nhgrp_blk_get(struct prestera_switch *sw,
2111                               u8 *hw_state, u32 buf_size /* Buffer in bytes */)
2112 {
2113         static struct prestera_msg_nh_chunk_resp resp;
2114         struct prestera_msg_nh_chunk_req req;
2115         u32 buf_offset;
2116         int err;
2117
2118         memset(&hw_state[0], 0, buf_size);
2119         buf_offset = 0;
2120         while (1) {
2121                 if (buf_offset >= buf_size)
2122                         break;
2123
2124                 memset(&req, 0, sizeof(req));
2125                 req.offset = __cpu_to_le32(buf_offset * 8); /* 8 bits in u8 */
2126                 err = prestera_cmd_ret(sw,
2127                                        PRESTERA_CMD_TYPE_ROUTER_NH_GRP_BLK_GET,
2128                                        &req.cmd, sizeof(req), &resp.ret,
2129                                        sizeof(resp));
2130                 if (err)
2131                         return err;
2132
2133                 memcpy(&hw_state[buf_offset], &resp.hw_state[0],
2134                        buf_offset + PRESTERA_MSG_CHUNK_SIZE > buf_size ?
2135                         buf_size - buf_offset : PRESTERA_MSG_CHUNK_SIZE);
2136                 buf_offset += PRESTERA_MSG_CHUNK_SIZE;
2137         }
2138
2139         return 0;
2140 }
2141
2142 int prestera_hw_nh_group_create(struct prestera_switch *sw, u16 nh_count,
2143                                 u32 *grp_id)
2144 {
2145         struct prestera_msg_nh_grp_req req = { .size = __cpu_to_le32((u32)nh_count) };
2146         struct prestera_msg_nh_grp_resp resp;
2147         int err;
2148
2149         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_NH_GRP_ADD,
2150                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2151         if (err)
2152                 return err;
2153
2154         *grp_id = __le32_to_cpu(resp.grp_id);
2155         return err;
2156 }
2157
2158 int prestera_hw_nh_group_delete(struct prestera_switch *sw, u16 nh_count,
2159                                 u32 grp_id)
2160 {
2161         struct prestera_msg_nh_grp_req req = {
2162             .grp_id = __cpu_to_le32(grp_id),
2163             .size = __cpu_to_le32(nh_count)
2164         };
2165
2166         return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_NH_GRP_DELETE,
2167                             &req.cmd, sizeof(req));
2168 }
2169
2170 int prestera_hw_rxtx_init(struct prestera_switch *sw,
2171                           struct prestera_rxtx_params *params)
2172 {
2173         struct prestera_msg_rxtx_resp resp;
2174         struct prestera_msg_rxtx_req req;
2175         int err;
2176
2177         req.use_sdma = params->use_sdma;
2178
2179         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT,
2180                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2181         if (err)
2182                 return err;
2183
2184         params->map_addr = __le32_to_cpu(resp.map_addr);
2185
2186         return 0;
2187 }
2188
2189 int prestera_hw_lag_member_add(struct prestera_port *port, u16 lag_id)
2190 {
2191         struct prestera_msg_lag_req req = {
2192                 .port = __cpu_to_le32(port->hw_id),
2193                 .dev = __cpu_to_le32(port->dev_id),
2194                 .lag_id = __cpu_to_le16(lag_id),
2195         };
2196
2197         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_ADD,
2198                             &req.cmd, sizeof(req));
2199 }
2200
2201 int prestera_hw_lag_member_del(struct prestera_port *port, u16 lag_id)
2202 {
2203         struct prestera_msg_lag_req req = {
2204                 .port = __cpu_to_le32(port->hw_id),
2205                 .dev = __cpu_to_le32(port->dev_id),
2206                 .lag_id = __cpu_to_le16(lag_id),
2207         };
2208
2209         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE,
2210                             &req.cmd, sizeof(req));
2211 }
2212
2213 int prestera_hw_lag_member_enable(struct prestera_port *port, u16 lag_id,
2214                                   bool enable)
2215 {
2216         struct prestera_msg_lag_req req = {
2217                 .port = __cpu_to_le32(port->hw_id),
2218                 .dev = __cpu_to_le32(port->dev_id),
2219                 .lag_id = __cpu_to_le16(lag_id),
2220         };
2221         u32 cmd;
2222
2223         cmd = enable ? PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE :
2224                         PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE;
2225
2226         return prestera_cmd(port->sw, cmd, &req.cmd, sizeof(req));
2227 }
2228
2229 int
2230 prestera_hw_cpu_code_counters_get(struct prestera_switch *sw, u8 code,
2231                                   enum prestera_hw_cpu_code_cnt_t counter_type,
2232                                   u64 *packet_count)
2233 {
2234         struct prestera_msg_cpu_code_counter_req req = {
2235                 .counter_type = counter_type,
2236                 .code = code,
2237         };
2238         struct mvsw_msg_cpu_code_counter_ret resp;
2239         int err;
2240
2241         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET,
2242                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2243         if (err)
2244                 return err;
2245
2246         *packet_count = __le64_to_cpu(resp.packet_count);
2247
2248         return 0;
2249 }
2250
2251 int prestera_hw_event_handler_register(struct prestera_switch *sw,
2252                                        enum prestera_event_type type,
2253                                        prestera_event_cb_t fn,
2254                                        void *arg)
2255 {
2256         struct prestera_fw_event_handler *eh;
2257
2258         eh = __find_event_handler(sw, type);
2259         if (eh)
2260                 return -EEXIST;
2261
2262         eh = kmalloc(sizeof(*eh), GFP_KERNEL);
2263         if (!eh)
2264                 return -ENOMEM;
2265
2266         eh->type = type;
2267         eh->func = fn;
2268         eh->arg = arg;
2269
2270         INIT_LIST_HEAD(&eh->list);
2271
2272         list_add_rcu(&eh->list, &sw->event_handlers);
2273
2274         return 0;
2275 }
2276
2277 void prestera_hw_event_handler_unregister(struct prestera_switch *sw,
2278                                           enum prestera_event_type type,
2279                                           prestera_event_cb_t fn)
2280 {
2281         struct prestera_fw_event_handler *eh;
2282
2283         eh = __find_event_handler(sw, type);
2284         if (!eh)
2285                 return;
2286
2287         list_del_rcu(&eh->list);
2288         kfree_rcu(eh, rcu);
2289 }
2290
2291 int prestera_hw_counter_trigger(struct prestera_switch *sw, u32 block_id)
2292 {
2293         struct prestera_msg_counter_req req = {
2294                 .block_id = __cpu_to_le32(block_id)
2295         };
2296
2297         return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_TRIGGER,
2298                             &req.cmd, sizeof(req));
2299 }
2300
2301 int prestera_hw_counter_abort(struct prestera_switch *sw)
2302 {
2303         struct prestera_msg_counter_req req;
2304
2305         return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_ABORT,
2306                             &req.cmd, sizeof(req));
2307 }
2308
2309 int prestera_hw_counters_get(struct prestera_switch *sw, u32 idx,
2310                              u32 *len, bool *done,
2311                              struct prestera_counter_stats *stats)
2312 {
2313         struct prestera_msg_counter_resp *resp;
2314         struct prestera_msg_counter_req req = {
2315                 .block_id = __cpu_to_le32(idx),
2316                 .num_counters = __cpu_to_le32(*len),
2317         };
2318         size_t size = struct_size(resp, stats, *len);
2319         int err, i;
2320
2321         resp = kmalloc(size, GFP_KERNEL);
2322         if (!resp)
2323                 return -ENOMEM;
2324
2325         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_GET,
2326                                &req.cmd, sizeof(req), &resp->ret, size);
2327         if (err)
2328                 goto free_buff;
2329
2330         for (i = 0; i < __le32_to_cpu(resp->num_counters); i++) {
2331                 stats[i].packets += __le64_to_cpu(resp->stats[i].packets);
2332                 stats[i].bytes += __le64_to_cpu(resp->stats[i].bytes);
2333         }
2334
2335         *len = __le32_to_cpu(resp->num_counters);
2336         *done = __le32_to_cpu(resp->done);
2337
2338 free_buff:
2339         kfree(resp);
2340         return err;
2341 }
2342
2343 int prestera_hw_counter_block_get(struct prestera_switch *sw,
2344                                   u32 client, u32 *block_id, u32 *offset,
2345                                   u32 *num_counters)
2346 {
2347         struct prestera_msg_counter_resp resp;
2348         struct prestera_msg_counter_req req = {
2349                 .client = __cpu_to_le32(client)
2350         };
2351         int err;
2352
2353         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_GET,
2354                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2355         if (err)
2356                 return err;
2357
2358         *block_id = __le32_to_cpu(resp.block_id);
2359         *offset = __le32_to_cpu(resp.offset);
2360         *num_counters = __le32_to_cpu(resp.num_counters);
2361
2362         return 0;
2363 }
2364
2365 int prestera_hw_counter_block_release(struct prestera_switch *sw,
2366                                       u32 block_id)
2367 {
2368         struct prestera_msg_counter_req req = {
2369                 .block_id = __cpu_to_le32(block_id)
2370         };
2371
2372         return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_RELEASE,
2373                             &req.cmd, sizeof(req));
2374 }
2375
2376 int prestera_hw_counter_clear(struct prestera_switch *sw, u32 block_id,
2377                               u32 counter_id)
2378 {
2379         struct prestera_msg_counter_req req = {
2380                 .block_id = __cpu_to_le32(block_id),
2381                 .num_counters = __cpu_to_le32(counter_id)
2382         };
2383
2384         return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_CLEAR,
2385                             &req.cmd, sizeof(req));
2386 }
2387
2388 int prestera_hw_policer_create(struct prestera_switch *sw, u8 type,
2389                                u32 *policer_id)
2390 {
2391         struct prestera_msg_policer_resp resp;
2392         struct prestera_msg_policer_req req = {
2393                 .type = type
2394         };
2395         int err;
2396
2397         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_POLICER_CREATE,
2398                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2399         if (err)
2400                 return err;
2401
2402         *policer_id = __le32_to_cpu(resp.id);
2403         return 0;
2404 }
2405
2406 int prestera_hw_policer_release(struct prestera_switch *sw,
2407                                 u32 policer_id)
2408 {
2409         struct prestera_msg_policer_req req = {
2410                 .id = __cpu_to_le32(policer_id)
2411         };
2412
2413         return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_RELEASE,
2414                             &req.cmd, sizeof(req));
2415 }
2416
2417 int prestera_hw_policer_sr_tcm_set(struct prestera_switch *sw,
2418                                    u32 policer_id, u64 cir, u32 cbs)
2419 {
2420         struct prestera_msg_policer_req req = {
2421                 .mode = PRESTERA_POLICER_MODE_SR_TCM,
2422                 .id = __cpu_to_le32(policer_id),
2423                 .sr_tcm = {
2424                         .cir = __cpu_to_le64(cir),
2425                         .cbs = __cpu_to_le32(cbs)
2426                 }
2427         };
2428
2429         return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_SET,
2430                             &req.cmd, sizeof(req));
2431 }
2432
2433 int prestera_hw_flood_domain_create(struct prestera_flood_domain *domain)
2434 {
2435         struct prestera_msg_flood_domain_create_resp resp;
2436         struct prestera_msg_flood_domain_create_req req;
2437         int err;
2438
2439         err = prestera_cmd_ret(domain->sw,
2440                                PRESTERA_CMD_TYPE_FLOOD_DOMAIN_CREATE, &req.cmd,
2441                                sizeof(req), &resp.ret, sizeof(resp));
2442         if (err)
2443                 return err;
2444
2445         domain->idx = __le32_to_cpu(resp.flood_domain_idx);
2446
2447         return 0;
2448 }
2449
2450 int prestera_hw_flood_domain_destroy(struct prestera_flood_domain *domain)
2451 {
2452         struct prestera_msg_flood_domain_destroy_req req = {
2453                 .flood_domain_idx = __cpu_to_le32(domain->idx),
2454         };
2455
2456         return prestera_cmd(domain->sw, PRESTERA_CMD_TYPE_FLOOD_DOMAIN_DESTROY,
2457                            &req.cmd, sizeof(req));
2458 }
2459
2460 int prestera_hw_flood_domain_ports_set(struct prestera_flood_domain *domain)
2461 {
2462         struct prestera_flood_domain_port *flood_domain_port;
2463         struct prestera_msg_flood_domain_ports_set_req *req;
2464         struct prestera_msg_flood_domain_port *ports;
2465         struct prestera_switch *sw = domain->sw;
2466         struct prestera_port *port;
2467         u32 ports_num = 0;
2468         int buf_size;
2469         void *buff;
2470         u16 lag_id;
2471         int err;
2472
2473         list_for_each_entry(flood_domain_port, &domain->flood_domain_port_list,
2474                             flood_domain_port_node)
2475                 ports_num++;
2476
2477         if (!ports_num)
2478                 return -EINVAL;
2479
2480         buf_size = sizeof(*req) + sizeof(*ports) * ports_num;
2481
2482         buff = kmalloc(buf_size, GFP_KERNEL);
2483         if (!buff)
2484                 return -ENOMEM;
2485
2486         req = buff;
2487         ports = buff + sizeof(*req);
2488
2489         req->flood_domain_idx = __cpu_to_le32(domain->idx);
2490         req->ports_num = __cpu_to_le32(ports_num);
2491
2492         list_for_each_entry(flood_domain_port, &domain->flood_domain_port_list,
2493                             flood_domain_port_node) {
2494                 if (netif_is_lag_master(flood_domain_port->dev)) {
2495                         if (prestera_lag_id(sw, flood_domain_port->dev,
2496                                             &lag_id)) {
2497                                 kfree(buff);
2498                                 return -EINVAL;
2499                         }
2500
2501                         ports->port_type =
2502                                 __cpu_to_le16(PRESTERA_HW_FLOOD_DOMAIN_PORT_TYPE_LAG);
2503                         ports->lag_id = __cpu_to_le16(lag_id);
2504                 } else {
2505                         port = prestera_port_dev_lower_find(flood_domain_port->dev);
2506
2507                         ports->port_type =
2508                                 __cpu_to_le16(PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT);
2509                         ports->dev_num = __cpu_to_le32(port->dev_id);
2510                         ports->port_num = __cpu_to_le32(port->hw_id);
2511                 }
2512
2513                 ports->vid = __cpu_to_le16(flood_domain_port->vid);
2514
2515                 ports++;
2516         }
2517
2518         err = prestera_cmd(sw, PRESTERA_CMD_TYPE_FLOOD_DOMAIN_PORTS_SET,
2519                            &req->cmd, buf_size);
2520
2521         kfree(buff);
2522
2523         return err;
2524 }
2525
2526 int prestera_hw_flood_domain_ports_reset(struct prestera_flood_domain *domain)
2527 {
2528         struct prestera_msg_flood_domain_ports_reset_req req = {
2529                 .flood_domain_idx = __cpu_to_le32(domain->idx),
2530         };
2531
2532         return prestera_cmd(domain->sw,
2533                            PRESTERA_CMD_TYPE_FLOOD_DOMAIN_PORTS_RESET, &req.cmd,
2534                            sizeof(req));
2535 }
2536
2537 int prestera_hw_mdb_create(struct prestera_mdb_entry *mdb)
2538 {
2539         struct prestera_msg_mdb_create_req req = {
2540                 .flood_domain_idx = __cpu_to_le32(mdb->flood_domain->idx),
2541                 .vid = __cpu_to_le16(mdb->vid),
2542         };
2543
2544         memcpy(req.mac, mdb->addr, ETH_ALEN);
2545
2546         return prestera_cmd(mdb->sw, PRESTERA_CMD_TYPE_MDB_CREATE, &req.cmd,
2547                             sizeof(req));
2548 }
2549
2550 int prestera_hw_mdb_destroy(struct prestera_mdb_entry *mdb)
2551 {
2552         struct prestera_msg_mdb_destroy_req req = {
2553                 .flood_domain_idx = __cpu_to_le32(mdb->flood_domain->idx),
2554                 .vid = __cpu_to_le16(mdb->vid),
2555         };
2556
2557         memcpy(req.mac, mdb->addr, ETH_ALEN);
2558
2559         return prestera_cmd(mdb->sw, PRESTERA_CMD_TYPE_MDB_DESTROY, &req.cmd,
2560                             sizeof(req));
2561 }