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