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