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
21enum 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
104enum {
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
122enum {
123	PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
124	PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
125};
126
127enum {
128	PRESTERA_CMD_ACK_OK,
129	PRESTERA_CMD_ACK_FAILED,
130
131	PRESTERA_CMD_ACK_MAX
132};
133
134enum {
135	PRESTERA_PORT_TP_NA,
136	PRESTERA_PORT_TP_MDI,
137	PRESTERA_PORT_TP_MDIX,
138	PRESTERA_PORT_TP_AUTO,
139};
140
141enum {
142	PRESTERA_PORT_FLOOD_TYPE_UC = 0,
143	PRESTERA_PORT_FLOOD_TYPE_MC = 1,
144};
145
146enum {
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
181enum {
182	PRESTERA_FC_NONE,
183	PRESTERA_FC_SYMMETRIC,
184	PRESTERA_FC_ASYMMETRIC,
185	PRESTERA_FC_SYMM_ASYMM,
186};
187
188enum {
189	PRESTERA_POLICER_MODE_SR_TCM
190};
191
192enum {
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
198struct 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
206enum {
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
212struct prestera_msg_cmd {
213	__le32 type;
214};
215
216struct prestera_msg_ret {
217	struct prestera_msg_cmd cmd;
218	__le32 status;
219};
220
221struct prestera_msg_common_req {
222	struct prestera_msg_cmd cmd;
223};
224
225struct prestera_msg_common_resp {
226	struct prestera_msg_ret ret;
227};
228
229struct 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
241struct 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
251struct 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
270struct prestera_msg_port_cap_param {
271	__le64 link_mode;
272	u8 type;
273	u8 fec;
274	u8 fc;
275	u8 transceiver;
276};
277
278struct prestera_msg_port_flood_param {
279	u8 type;
280	u8 enable;
281	u8 __pad[2];
282};
283
284union 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
338struct 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
346struct prestera_msg_port_attr_resp {
347	struct prestera_msg_ret ret;
348	union prestera_msg_port_param param;
349};
350
351struct prestera_msg_port_stats_resp {
352	struct prestera_msg_ret ret;
353	__le64 stats[PRESTERA_PORT_CNT_MAX];
354};
355
356struct prestera_msg_port_info_req {
357	struct prestera_msg_cmd cmd;
358	__le32 port;
359};
360
361struct 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
369struct 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
378struct 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
395struct 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
403struct prestera_msg_bridge_resp {
404	struct prestera_msg_ret ret;
405	__le16 bridge;
406	u8 pad[2];
407};
408
409struct 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
417struct prestera_msg_vtcam_destroy_req {
418	struct prestera_msg_cmd cmd;
419	__le32 vtcam_id;
420};
421
422struct 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
431struct prestera_msg_vtcam_rule_del_req {
432	struct prestera_msg_cmd cmd;
433	__le32 vtcam_id;
434	__le32 id;
435};
436
437struct 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
451struct prestera_msg_vtcam_resp {
452	struct prestera_msg_ret ret;
453	__le32 vtcam_id;
454	__le32 rule_id;
455};
456
457struct 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
474struct prestera_msg_counter_req {
475	struct prestera_msg_cmd cmd;
476	__le32 client;
477	__le32 block_id;
478	__le32 num_counters;
479};
480
481struct prestera_msg_counter_stats {
482	__le64 packets;
483	__le64 bytes;
484};
485
486struct 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
495struct 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
503struct prestera_msg_span_resp {
504	struct prestera_msg_ret ret;
505	u8 id;
506	u8 pad[3];
507};
508
509struct 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
518struct prestera_msg_rxtx_req {
519	struct prestera_msg_cmd cmd;
520	u8 use_sdma;
521	u8 pad[3];
522};
523
524struct prestera_msg_rxtx_resp {
525	struct prestera_msg_ret ret;
526	__le32 map_addr;
527};
528
529struct 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
543struct 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
552struct 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
560struct 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
570struct prestera_msg_rif_resp {
571	struct prestera_msg_ret ret;
572	__le16 rif_id;
573	u8 __pad[2];
574};
575
576struct 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
585struct 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
592struct prestera_msg_nh_chunk_req {
593	struct prestera_msg_cmd cmd;
594	__le32 offset;
595};
596
597struct prestera_msg_nh_chunk_resp {
598	struct prestera_msg_ret ret;
599	u8 hw_state[PRESTERA_MSG_CHUNK_SIZE];
600};
601
602struct prestera_msg_nh_grp_req {
603	struct prestera_msg_cmd cmd;
604	__le32 grp_id;
605	__le32 size;
606};
607
608struct prestera_msg_nh_grp_resp {
609	struct prestera_msg_ret ret;
610	__le32 grp_id;
611};
612
613struct prestera_msg_vr_req {
614	struct prestera_msg_cmd cmd;
615	__le16 vr_id;
616	u8 __pad[2];
617};
618
619struct prestera_msg_vr_resp {
620	struct prestera_msg_ret ret;
621	__le16 vr_id;
622	u8 __pad[2];
623};
624
625struct 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
633struct 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
640struct mvsw_msg_cpu_code_counter_ret {
641	struct prestera_msg_ret ret;
642	__le64 packet_count;
643};
644
645struct 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
660struct prestera_msg_policer_resp {
661	struct prestera_msg_ret ret;
662	__le32 id;
663};
664
665struct prestera_msg_event {
666	__le16 type;
667	__le16 id;
668};
669
670struct prestera_msg_event_port {
671	struct prestera_msg_event id;
672	__le32 port_id;
673	struct prestera_msg_event_port_param param;
674};
675
676union prestera_msg_event_fdb_param {
677	u8 mac[ETH_ALEN];
678};
679
680struct 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
691struct prestera_msg_flood_domain_create_req {
692	struct prestera_msg_cmd cmd;
693};
694
695struct prestera_msg_flood_domain_create_resp {
696	struct prestera_msg_ret ret;
697	__le32 flood_domain_idx;
698};
699
700struct prestera_msg_flood_domain_destroy_req {
701	struct prestera_msg_cmd cmd;
702	__le32 flood_domain_idx;
703};
704
705struct prestera_msg_flood_domain_ports_set_req {
706	struct prestera_msg_cmd cmd;
707	__le32 flood_domain_idx;
708	__le32 ports_num;
709};
710
711struct prestera_msg_flood_domain_ports_reset_req {
712	struct prestera_msg_cmd cmd;
713	__le32 flood_domain_idx;
714};
715
716struct 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
728struct 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
735struct 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
742static 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
808static u8 prestera_hw_mdix_to_eth(u8 mode);
809static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause);
810
811static 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
834static 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
842static 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
851static 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
860static 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
884static 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
908static 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
915static 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
929static 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
947static 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
977static 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
993static 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
1007static 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
1021int 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
1042int 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
1054int 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
1085void prestera_hw_switch_fini(struct prestera_switch *sw)
1086{
1087	WARN_ON(!list_empty(&sw->event_handlers));
1088}
1089
1090int 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
1103int 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
1134int 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
1160int 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
1190int 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
1216int 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
1231int 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
1245int 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
1261int 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
1285static 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
1306int 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
1331int 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
1341static int
1342prestera_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
1369int 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);
1413free_buff:
1414	kfree(buff);
1415	return err;
1416}
1417
1418int 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
1430int 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
1451int 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
1471int 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
1490int 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
1509int 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
1525int 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
1535int 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
1555int 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
1575int 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
1588int 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
1659int 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
1674int 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
1692int 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
1710int 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
1726int 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
1736int 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
1746int 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
1761int 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
1773int 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
1786int 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
1804int 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
1821int 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
1839int 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
1856int 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
1870int 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
1881int 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
1897int 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
1912int 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
1928int 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
1945int 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
1955int 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
1967int 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
1979static 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
2001int 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
2023int 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
2039int 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
2054int 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
2064int 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
2078int 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
2091int 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
2110int 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
2142int 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
2158int 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
2170int 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
2189int 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
2201int 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
2213int 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
2229int
2230prestera_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
2251int 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
2277void 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
2291int 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
2301int 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
2309int 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
2338free_buff:
2339	kfree(resp);
2340	return err;
2341}
2342
2343int 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
2365int 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
2376int 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
2388int 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
2406int 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
2417int 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
2433int 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
2450int 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
2460int 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
2526int 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
2537int 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
2550int 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}
2562