GNU Linux-libre 5.10.215-gnu1
[releases.git] / drivers / net / ethernet / marvell / prestera / prestera_hw.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
3
4 #include <linux/etherdevice.h>
5 #include <linux/ethtool.h>
6 #include <linux/list.h>
7
8 #include "prestera.h"
9 #include "prestera_hw.h"
10
11 #define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
12
13 #define PRESTERA_MIN_MTU 64
14
15 enum prestera_cmd_type_t {
16         PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1,
17         PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2,
18
19         PRESTERA_CMD_TYPE_PORT_ATTR_SET = 0x100,
20         PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101,
21         PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110,
22
23         PRESTERA_CMD_TYPE_VLAN_CREATE = 0x200,
24         PRESTERA_CMD_TYPE_VLAN_DELETE = 0x201,
25         PRESTERA_CMD_TYPE_VLAN_PORT_SET = 0x202,
26         PRESTERA_CMD_TYPE_VLAN_PVID_SET = 0x203,
27
28         PRESTERA_CMD_TYPE_FDB_ADD = 0x300,
29         PRESTERA_CMD_TYPE_FDB_DELETE = 0x301,
30         PRESTERA_CMD_TYPE_FDB_FLUSH_PORT = 0x310,
31         PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN = 0x311,
32         PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN = 0x312,
33
34         PRESTERA_CMD_TYPE_BRIDGE_CREATE = 0x400,
35         PRESTERA_CMD_TYPE_BRIDGE_DELETE = 0x401,
36         PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD = 0x402,
37         PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE = 0x403,
38
39         PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
40         PRESTERA_CMD_TYPE_RXTX_PORT_INIT = 0x801,
41
42         PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
43
44         PRESTERA_CMD_TYPE_ACK = 0x10000,
45         PRESTERA_CMD_TYPE_MAX
46 };
47
48 enum {
49         PRESTERA_CMD_PORT_ATTR_ADMIN_STATE = 1,
50         PRESTERA_CMD_PORT_ATTR_MTU = 3,
51         PRESTERA_CMD_PORT_ATTR_MAC = 4,
52         PRESTERA_CMD_PORT_ATTR_SPEED = 5,
53         PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6,
54         PRESTERA_CMD_PORT_ATTR_LEARNING = 7,
55         PRESTERA_CMD_PORT_ATTR_FLOOD = 8,
56         PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9,
57         PRESTERA_CMD_PORT_ATTR_REMOTE_CAPABILITY = 10,
58         PRESTERA_CMD_PORT_ATTR_REMOTE_FC = 11,
59         PRESTERA_CMD_PORT_ATTR_LINK_MODE = 12,
60         PRESTERA_CMD_PORT_ATTR_TYPE = 13,
61         PRESTERA_CMD_PORT_ATTR_FEC = 14,
62         PRESTERA_CMD_PORT_ATTR_AUTONEG = 15,
63         PRESTERA_CMD_PORT_ATTR_DUPLEX = 16,
64         PRESTERA_CMD_PORT_ATTR_STATS = 17,
65         PRESTERA_CMD_PORT_ATTR_MDIX = 18,
66         PRESTERA_CMD_PORT_ATTR_AUTONEG_RESTART = 19,
67 };
68
69 enum {
70         PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
71         PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
72 };
73
74 enum {
75         PRESTERA_CMD_ACK_OK,
76         PRESTERA_CMD_ACK_FAILED,
77
78         PRESTERA_CMD_ACK_MAX
79 };
80
81 enum {
82         PRESTERA_PORT_TP_NA,
83         PRESTERA_PORT_TP_MDI,
84         PRESTERA_PORT_TP_MDIX,
85         PRESTERA_PORT_TP_AUTO,
86 };
87
88 enum {
89         PRESTERA_PORT_GOOD_OCTETS_RCV_CNT,
90         PRESTERA_PORT_BAD_OCTETS_RCV_CNT,
91         PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT,
92         PRESTERA_PORT_BRDC_PKTS_RCV_CNT,
93         PRESTERA_PORT_MC_PKTS_RCV_CNT,
94         PRESTERA_PORT_PKTS_64L_CNT,
95         PRESTERA_PORT_PKTS_65TO127L_CNT,
96         PRESTERA_PORT_PKTS_128TO255L_CNT,
97         PRESTERA_PORT_PKTS_256TO511L_CNT,
98         PRESTERA_PORT_PKTS_512TO1023L_CNT,
99         PRESTERA_PORT_PKTS_1024TOMAXL_CNT,
100         PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT,
101         PRESTERA_PORT_MC_PKTS_SENT_CNT,
102         PRESTERA_PORT_BRDC_PKTS_SENT_CNT,
103         PRESTERA_PORT_FC_SENT_CNT,
104         PRESTERA_PORT_GOOD_FC_RCV_CNT,
105         PRESTERA_PORT_DROP_EVENTS_CNT,
106         PRESTERA_PORT_UNDERSIZE_PKTS_CNT,
107         PRESTERA_PORT_FRAGMENTS_PKTS_CNT,
108         PRESTERA_PORT_OVERSIZE_PKTS_CNT,
109         PRESTERA_PORT_JABBER_PKTS_CNT,
110         PRESTERA_PORT_MAC_RCV_ERROR_CNT,
111         PRESTERA_PORT_BAD_CRC_CNT,
112         PRESTERA_PORT_COLLISIONS_CNT,
113         PRESTERA_PORT_LATE_COLLISIONS_CNT,
114         PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT,
115         PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT,
116         PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT,
117         PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT,
118         PRESTERA_PORT_GOOD_OCTETS_SENT_CNT,
119
120         PRESTERA_PORT_CNT_MAX
121 };
122
123 enum {
124         PRESTERA_FC_NONE,
125         PRESTERA_FC_SYMMETRIC,
126         PRESTERA_FC_ASYMMETRIC,
127         PRESTERA_FC_SYMM_ASYMM,
128 };
129
130 struct prestera_fw_event_handler {
131         struct list_head list;
132         struct rcu_head rcu;
133         enum prestera_event_type type;
134         prestera_event_cb_t func;
135         void *arg;
136 };
137
138 struct prestera_msg_cmd {
139         u32 type;
140 };
141
142 struct prestera_msg_ret {
143         struct prestera_msg_cmd cmd;
144         u32 status;
145 };
146
147 struct prestera_msg_common_req {
148         struct prestera_msg_cmd cmd;
149 };
150
151 struct prestera_msg_common_resp {
152         struct prestera_msg_ret ret;
153 };
154
155 union prestera_msg_switch_param {
156         u8 mac[ETH_ALEN];
157         u32 ageing_timeout_ms;
158 };
159
160 struct prestera_msg_switch_attr_req {
161         struct prestera_msg_cmd cmd;
162         u32 attr;
163         union prestera_msg_switch_param param;
164 };
165
166 struct prestera_msg_switch_init_resp {
167         struct prestera_msg_ret ret;
168         u32 port_count;
169         u32 mtu_max;
170         u8  switch_id;
171 };
172
173 struct prestera_msg_port_autoneg_param {
174         u64 link_mode;
175         u8  enable;
176         u8  fec;
177 };
178
179 struct prestera_msg_port_cap_param {
180         u64 link_mode;
181         u8  type;
182         u8  fec;
183         u8  transceiver;
184 };
185
186 struct prestera_msg_port_mdix_param {
187         u8 status;
188         u8 admin_mode;
189 };
190
191 union prestera_msg_port_param {
192         u8  admin_state;
193         u8  oper_state;
194         u32 mtu;
195         u8  mac[ETH_ALEN];
196         u8  accept_frm_type;
197         u32 speed;
198         u8 learning;
199         u8 flood;
200         u32 link_mode;
201         u8  type;
202         u8  duplex;
203         u8  fec;
204         u8  fc;
205         struct prestera_msg_port_mdix_param mdix;
206         struct prestera_msg_port_autoneg_param autoneg;
207         struct prestera_msg_port_cap_param cap;
208 };
209
210 struct prestera_msg_port_attr_req {
211         struct prestera_msg_cmd cmd;
212         u32 attr;
213         u32 port;
214         u32 dev;
215         union prestera_msg_port_param param;
216 };
217
218 struct prestera_msg_port_attr_resp {
219         struct prestera_msg_ret ret;
220         union prestera_msg_port_param param;
221 };
222
223 struct prestera_msg_port_stats_resp {
224         struct prestera_msg_ret ret;
225         u64 stats[PRESTERA_PORT_CNT_MAX];
226 };
227
228 struct prestera_msg_port_info_req {
229         struct prestera_msg_cmd cmd;
230         u32 port;
231 };
232
233 struct prestera_msg_port_info_resp {
234         struct prestera_msg_ret ret;
235         u32 hw_id;
236         u32 dev_id;
237         u16 fp_id;
238 };
239
240 struct prestera_msg_vlan_req {
241         struct prestera_msg_cmd cmd;
242         u32 port;
243         u32 dev;
244         u16 vid;
245         u8  is_member;
246         u8  is_tagged;
247 };
248
249 struct prestera_msg_fdb_req {
250         struct prestera_msg_cmd cmd;
251         u8 dest_type;
252         u32 port;
253         u32 dev;
254         u8  mac[ETH_ALEN];
255         u16 vid;
256         u8  dynamic;
257         u32 flush_mode;
258 };
259
260 struct prestera_msg_bridge_req {
261         struct prestera_msg_cmd cmd;
262         u32 port;
263         u32 dev;
264         u16 bridge;
265 };
266
267 struct prestera_msg_bridge_resp {
268         struct prestera_msg_ret ret;
269         u16 bridge;
270 };
271
272 struct prestera_msg_stp_req {
273         struct prestera_msg_cmd cmd;
274         u32 port;
275         u32 dev;
276         u16 vid;
277         u8  state;
278 };
279
280 struct prestera_msg_rxtx_req {
281         struct prestera_msg_cmd cmd;
282         u8 use_sdma;
283 };
284
285 struct prestera_msg_rxtx_resp {
286         struct prestera_msg_ret ret;
287         u32 map_addr;
288 };
289
290 struct prestera_msg_rxtx_port_req {
291         struct prestera_msg_cmd cmd;
292         u32 port;
293         u32 dev;
294 };
295
296 struct prestera_msg_event {
297         u16 type;
298         u16 id;
299 };
300
301 union prestera_msg_event_port_param {
302         u32 oper_state;
303 };
304
305 struct prestera_msg_event_port {
306         struct prestera_msg_event id;
307         u32 port_id;
308         union prestera_msg_event_port_param param;
309 };
310
311 union prestera_msg_event_fdb_param {
312         u8 mac[ETH_ALEN];
313 };
314
315 struct prestera_msg_event_fdb {
316         struct prestera_msg_event id;
317         u8 dest_type;
318         u32 port_id;
319         u32 vid;
320         union prestera_msg_event_fdb_param param;
321 };
322
323 static int __prestera_cmd_ret(struct prestera_switch *sw,
324                               enum prestera_cmd_type_t type,
325                               struct prestera_msg_cmd *cmd, size_t clen,
326                               struct prestera_msg_ret *ret, size_t rlen,
327                               int waitms)
328 {
329         struct prestera_device *dev = sw->dev;
330         int err;
331
332         cmd->type = type;
333
334         err = dev->send_req(dev, cmd, clen, ret, rlen, waitms);
335         if (err)
336                 return err;
337
338         if (ret->cmd.type != PRESTERA_CMD_TYPE_ACK)
339                 return -EBADE;
340         if (ret->status != PRESTERA_CMD_ACK_OK)
341                 return -EINVAL;
342
343         return 0;
344 }
345
346 static int prestera_cmd_ret(struct prestera_switch *sw,
347                             enum prestera_cmd_type_t type,
348                             struct prestera_msg_cmd *cmd, size_t clen,
349                             struct prestera_msg_ret *ret, size_t rlen)
350 {
351         return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0);
352 }
353
354 static int prestera_cmd_ret_wait(struct prestera_switch *sw,
355                                  enum prestera_cmd_type_t type,
356                                  struct prestera_msg_cmd *cmd, size_t clen,
357                                  struct prestera_msg_ret *ret, size_t rlen,
358                                  int waitms)
359 {
360         return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms);
361 }
362
363 static int prestera_cmd(struct prestera_switch *sw,
364                         enum prestera_cmd_type_t type,
365                         struct prestera_msg_cmd *cmd, size_t clen)
366 {
367         struct prestera_msg_common_resp resp;
368
369         return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp));
370 }
371
372 static int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt)
373 {
374         struct prestera_msg_event_port *hw_evt = msg;
375
376         if (evt->id != PRESTERA_PORT_EVENT_STATE_CHANGED)
377                 return -EINVAL;
378
379         evt->port_evt.data.oper_state = hw_evt->param.oper_state;
380         evt->port_evt.port_id = hw_evt->port_id;
381
382         return 0;
383 }
384
385 static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt)
386 {
387         struct prestera_msg_event_fdb *hw_evt = msg;
388
389         evt->fdb_evt.port_id = hw_evt->port_id;
390         evt->fdb_evt.vid = hw_evt->vid;
391
392         ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac);
393
394         return 0;
395 }
396
397 static struct prestera_fw_evt_parser {
398         int (*func)(void *msg, struct prestera_event *evt);
399 } fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = {
400         [PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt },
401         [PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt },
402 };
403
404 static struct prestera_fw_event_handler *
405 __find_event_handler(const struct prestera_switch *sw,
406                      enum prestera_event_type type)
407 {
408         struct prestera_fw_event_handler *eh;
409
410         list_for_each_entry_rcu(eh, &sw->event_handlers, list) {
411                 if (eh->type == type)
412                         return eh;
413         }
414
415         return NULL;
416 }
417
418 static int prestera_find_event_handler(const struct prestera_switch *sw,
419                                        enum prestera_event_type type,
420                                        struct prestera_fw_event_handler *eh)
421 {
422         struct prestera_fw_event_handler *tmp;
423         int err = 0;
424
425         rcu_read_lock();
426         tmp = __find_event_handler(sw, type);
427         if (tmp)
428                 *eh = *tmp;
429         else
430                 err = -ENOENT;
431         rcu_read_unlock();
432
433         return err;
434 }
435
436 static int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size)
437 {
438         struct prestera_switch *sw = dev->priv;
439         struct prestera_msg_event *msg = buf;
440         struct prestera_fw_event_handler eh;
441         struct prestera_event evt;
442         int err;
443
444         if (msg->type >= PRESTERA_EVENT_TYPE_MAX)
445                 return -EINVAL;
446         if (!fw_event_parsers[msg->type].func)
447                 return -ENOENT;
448
449         err = prestera_find_event_handler(sw, msg->type, &eh);
450         if (err)
451                 return err;
452
453         evt.id = msg->id;
454
455         err = fw_event_parsers[msg->type].func(buf, &evt);
456         if (err)
457                 return err;
458
459         eh.func(sw, &evt, eh.arg);
460
461         return 0;
462 }
463
464 static void prestera_pkt_recv(struct prestera_device *dev)
465 {
466         struct prestera_switch *sw = dev->priv;
467         struct prestera_fw_event_handler eh;
468         struct prestera_event ev;
469         int err;
470
471         ev.id = PRESTERA_RXTX_EVENT_RCV_PKT;
472
473         err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh);
474         if (err)
475                 return;
476
477         eh.func(sw, &ev, eh.arg);
478 }
479
480 int prestera_hw_port_info_get(const struct prestera_port *port,
481                               u32 *dev_id, u32 *hw_id, u16 *fp_id)
482 {
483         struct prestera_msg_port_info_req req = {
484                 .port = port->id,
485         };
486         struct prestera_msg_port_info_resp resp;
487         int err;
488
489         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET,
490                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
491         if (err)
492                 return err;
493
494         *dev_id = resp.dev_id;
495         *hw_id = resp.hw_id;
496         *fp_id = resp.fp_id;
497
498         return 0;
499 }
500
501 int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac)
502 {
503         struct prestera_msg_switch_attr_req req = {
504                 .attr = PRESTERA_CMD_SWITCH_ATTR_MAC,
505         };
506
507         ether_addr_copy(req.param.mac, mac);
508
509         return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
510                             &req.cmd, sizeof(req));
511 }
512
513 int prestera_hw_switch_init(struct prestera_switch *sw)
514 {
515         struct prestera_msg_switch_init_resp resp;
516         struct prestera_msg_common_req req;
517         int err;
518
519         INIT_LIST_HEAD(&sw->event_handlers);
520
521         err = prestera_cmd_ret_wait(sw, PRESTERA_CMD_TYPE_SWITCH_INIT,
522                                     &req.cmd, sizeof(req),
523                                     &resp.ret, sizeof(resp),
524                                     PRESTERA_SWITCH_INIT_TIMEOUT_MS);
525         if (err)
526                 return err;
527
528         sw->dev->recv_msg = prestera_evt_recv;
529         sw->dev->recv_pkt = prestera_pkt_recv;
530         sw->port_count = resp.port_count;
531         sw->mtu_min = PRESTERA_MIN_MTU;
532         sw->mtu_max = resp.mtu_max;
533         sw->id = resp.switch_id;
534
535         return 0;
536 }
537
538 void prestera_hw_switch_fini(struct prestera_switch *sw)
539 {
540         WARN_ON(!list_empty(&sw->event_handlers));
541 }
542
543 int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms)
544 {
545         struct prestera_msg_switch_attr_req req = {
546                 .attr = PRESTERA_CMD_SWITCH_ATTR_AGEING,
547                 .param = {
548                         .ageing_timeout_ms = ageing_ms,
549                 },
550         };
551
552         return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
553                             &req.cmd, sizeof(req));
554 }
555
556 int prestera_hw_port_state_set(const struct prestera_port *port,
557                                bool admin_state)
558 {
559         struct prestera_msg_port_attr_req req = {
560                 .attr = PRESTERA_CMD_PORT_ATTR_ADMIN_STATE,
561                 .port = port->hw_id,
562                 .dev = port->dev_id,
563                 .param = {
564                         .admin_state = admin_state,
565                 }
566         };
567
568         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
569                             &req.cmd, sizeof(req));
570 }
571
572 int prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu)
573 {
574         struct prestera_msg_port_attr_req req = {
575                 .attr = PRESTERA_CMD_PORT_ATTR_MTU,
576                 .port = port->hw_id,
577                 .dev = port->dev_id,
578                 .param = {
579                         .mtu = mtu,
580                 }
581         };
582
583         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
584                             &req.cmd, sizeof(req));
585 }
586
587 int prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac)
588 {
589         struct prestera_msg_port_attr_req req = {
590                 .attr = PRESTERA_CMD_PORT_ATTR_MAC,
591                 .port = port->hw_id,
592                 .dev = port->dev_id,
593         };
594
595         ether_addr_copy(req.param.mac, mac);
596
597         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
598                             &req.cmd, sizeof(req));
599 }
600
601 int prestera_hw_port_accept_frm_type(struct prestera_port *port,
602                                      enum prestera_accept_frm_type type)
603 {
604         struct prestera_msg_port_attr_req req = {
605                 .attr = PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE,
606                 .port = port->hw_id,
607                 .dev = port->dev_id,
608                 .param = {
609                         .accept_frm_type = type,
610                 }
611         };
612
613         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
614                             &req.cmd, sizeof(req));
615 }
616
617 int prestera_hw_port_cap_get(const struct prestera_port *port,
618                              struct prestera_port_caps *caps)
619 {
620         struct prestera_msg_port_attr_req req = {
621                 .attr = PRESTERA_CMD_PORT_ATTR_CAPABILITY,
622                 .port = port->hw_id,
623                 .dev = port->dev_id,
624         };
625         struct prestera_msg_port_attr_resp resp;
626         int err;
627
628         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
629                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
630         if (err)
631                 return err;
632
633         caps->supp_link_modes = resp.param.cap.link_mode;
634         caps->transceiver = resp.param.cap.transceiver;
635         caps->supp_fec = resp.param.cap.fec;
636         caps->type = resp.param.cap.type;
637
638         return err;
639 }
640
641 int prestera_hw_port_remote_cap_get(const struct prestera_port *port,
642                                     u64 *link_mode_bitmap)
643 {
644         struct prestera_msg_port_attr_req req = {
645                 .attr = PRESTERA_CMD_PORT_ATTR_REMOTE_CAPABILITY,
646                 .port = port->hw_id,
647                 .dev = port->dev_id,
648         };
649         struct prestera_msg_port_attr_resp resp;
650         int err;
651
652         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
653                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
654         if (err)
655                 return err;
656
657         *link_mode_bitmap = resp.param.cap.link_mode;
658
659         return 0;
660 }
661
662 int prestera_hw_port_remote_fc_get(const struct prestera_port *port,
663                                    bool *pause, bool *asym_pause)
664 {
665         struct prestera_msg_port_attr_req req = {
666                 .attr = PRESTERA_CMD_PORT_ATTR_REMOTE_FC,
667                 .port = port->hw_id,
668                 .dev = port->dev_id,
669         };
670         struct prestera_msg_port_attr_resp resp;
671         int err;
672
673         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
674                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
675         if (err)
676                 return err;
677
678         switch (resp.param.fc) {
679         case PRESTERA_FC_SYMMETRIC:
680                 *pause = true;
681                 *asym_pause = false;
682                 break;
683         case PRESTERA_FC_ASYMMETRIC:
684                 *pause = false;
685                 *asym_pause = true;
686                 break;
687         case PRESTERA_FC_SYMM_ASYMM:
688                 *pause = true;
689                 *asym_pause = true;
690                 break;
691         default:
692                 *pause = false;
693                 *asym_pause = false;
694         }
695
696         return 0;
697 }
698
699 int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
700 {
701         struct prestera_msg_port_attr_req req = {
702                 .attr = PRESTERA_CMD_PORT_ATTR_TYPE,
703                 .port = port->hw_id,
704                 .dev = port->dev_id,
705         };
706         struct prestera_msg_port_attr_resp resp;
707         int err;
708
709         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
710                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
711         if (err)
712                 return err;
713
714         *type = resp.param.type;
715
716         return 0;
717 }
718
719 int prestera_hw_port_fec_get(const struct prestera_port *port, u8 *fec)
720 {
721         struct prestera_msg_port_attr_req req = {
722                 .attr = PRESTERA_CMD_PORT_ATTR_FEC,
723                 .port = port->hw_id,
724                 .dev = port->dev_id,
725         };
726         struct prestera_msg_port_attr_resp resp;
727         int err;
728
729         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
730                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
731         if (err)
732                 return err;
733
734         *fec = resp.param.fec;
735
736         return 0;
737 }
738
739 int prestera_hw_port_fec_set(const struct prestera_port *port, u8 fec)
740 {
741         struct prestera_msg_port_attr_req req = {
742                 .attr = PRESTERA_CMD_PORT_ATTR_FEC,
743                 .port = port->hw_id,
744                 .dev = port->dev_id,
745                 .param = {
746                         .fec = fec,
747                 }
748         };
749
750         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
751                             &req.cmd, sizeof(req));
752 }
753
754 static u8 prestera_hw_mdix_to_eth(u8 mode)
755 {
756         switch (mode) {
757         case PRESTERA_PORT_TP_MDI:
758                 return ETH_TP_MDI;
759         case PRESTERA_PORT_TP_MDIX:
760                 return ETH_TP_MDI_X;
761         case PRESTERA_PORT_TP_AUTO:
762                 return ETH_TP_MDI_AUTO;
763         default:
764                 return ETH_TP_MDI_INVALID;
765         }
766 }
767
768 static u8 prestera_hw_mdix_from_eth(u8 mode)
769 {
770         switch (mode) {
771         case ETH_TP_MDI:
772                 return PRESTERA_PORT_TP_MDI;
773         case ETH_TP_MDI_X:
774                 return PRESTERA_PORT_TP_MDIX;
775         case ETH_TP_MDI_AUTO:
776                 return PRESTERA_PORT_TP_AUTO;
777         default:
778                 return PRESTERA_PORT_TP_NA;
779         }
780 }
781
782 int prestera_hw_port_mdix_get(const struct prestera_port *port, u8 *status,
783                               u8 *admin_mode)
784 {
785         struct prestera_msg_port_attr_req req = {
786                 .attr = PRESTERA_CMD_PORT_ATTR_MDIX,
787                 .port = port->hw_id,
788                 .dev = port->dev_id,
789         };
790         struct prestera_msg_port_attr_resp resp;
791         int err;
792
793         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
794                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
795         if (err)
796                 return err;
797
798         *status = prestera_hw_mdix_to_eth(resp.param.mdix.status);
799         *admin_mode = prestera_hw_mdix_to_eth(resp.param.mdix.admin_mode);
800
801         return 0;
802 }
803
804 int prestera_hw_port_mdix_set(const struct prestera_port *port, u8 mode)
805 {
806         struct prestera_msg_port_attr_req req = {
807                 .attr = PRESTERA_CMD_PORT_ATTR_MDIX,
808                 .port = port->hw_id,
809                 .dev = port->dev_id,
810         };
811
812         req.param.mdix.admin_mode = prestera_hw_mdix_from_eth(mode);
813
814         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
815                             &req.cmd, sizeof(req));
816 }
817
818 int prestera_hw_port_link_mode_set(const struct prestera_port *port, u32 mode)
819 {
820         struct prestera_msg_port_attr_req req = {
821                 .attr = PRESTERA_CMD_PORT_ATTR_LINK_MODE,
822                 .port = port->hw_id,
823                 .dev = port->dev_id,
824                 .param = {
825                         .link_mode = mode,
826                 }
827         };
828
829         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
830                             &req.cmd, sizeof(req));
831 }
832
833 int prestera_hw_port_link_mode_get(const struct prestera_port *port, u32 *mode)
834 {
835         struct prestera_msg_port_attr_req req = {
836                 .attr = PRESTERA_CMD_PORT_ATTR_LINK_MODE,
837                 .port = port->hw_id,
838                 .dev = port->dev_id,
839         };
840         struct prestera_msg_port_attr_resp resp;
841         int err;
842
843         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
844                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
845         if (err)
846                 return err;
847
848         *mode = resp.param.link_mode;
849
850         return 0;
851 }
852
853 int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed)
854 {
855         struct prestera_msg_port_attr_req req = {
856                 .attr = PRESTERA_CMD_PORT_ATTR_SPEED,
857                 .port = port->hw_id,
858                 .dev = port->dev_id,
859         };
860         struct prestera_msg_port_attr_resp resp;
861         int err;
862
863         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
864                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
865         if (err)
866                 return err;
867
868         *speed = resp.param.speed;
869
870         return 0;
871 }
872
873 int prestera_hw_port_autoneg_set(const struct prestera_port *port,
874                                  bool autoneg, u64 link_modes, u8 fec)
875 {
876         struct prestera_msg_port_attr_req req = {
877                 .attr = PRESTERA_CMD_PORT_ATTR_AUTONEG,
878                 .port = port->hw_id,
879                 .dev = port->dev_id,
880                 .param = {
881                         .autoneg = {
882                                 .link_mode = link_modes,
883                                 .enable = autoneg,
884                                 .fec = fec,
885                         }
886                 }
887         };
888
889         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
890                             &req.cmd, sizeof(req));
891 }
892
893 int prestera_hw_port_autoneg_restart(struct prestera_port *port)
894 {
895         struct prestera_msg_port_attr_req req = {
896                 .attr = PRESTERA_CMD_PORT_ATTR_AUTONEG_RESTART,
897                 .port = port->hw_id,
898                 .dev = port->dev_id,
899         };
900
901         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
902                             &req.cmd, sizeof(req));
903 }
904
905 int prestera_hw_port_duplex_get(const struct prestera_port *port, u8 *duplex)
906 {
907         struct prestera_msg_port_attr_req req = {
908                 .attr = PRESTERA_CMD_PORT_ATTR_DUPLEX,
909                 .port = port->hw_id,
910                 .dev = port->dev_id,
911         };
912         struct prestera_msg_port_attr_resp resp;
913         int err;
914
915         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
916                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
917         if (err)
918                 return err;
919
920         *duplex = resp.param.duplex;
921
922         return 0;
923 }
924
925 int prestera_hw_port_stats_get(const struct prestera_port *port,
926                                struct prestera_port_stats *st)
927 {
928         struct prestera_msg_port_attr_req req = {
929                 .attr = PRESTERA_CMD_PORT_ATTR_STATS,
930                 .port = port->hw_id,
931                 .dev = port->dev_id,
932         };
933         struct prestera_msg_port_stats_resp resp;
934         u64 *hw = resp.stats;
935         int err;
936
937         err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
938                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
939         if (err)
940                 return err;
941
942         st->good_octets_received = hw[PRESTERA_PORT_GOOD_OCTETS_RCV_CNT];
943         st->bad_octets_received = hw[PRESTERA_PORT_BAD_OCTETS_RCV_CNT];
944         st->mac_trans_error = hw[PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT];
945         st->broadcast_frames_received = hw[PRESTERA_PORT_BRDC_PKTS_RCV_CNT];
946         st->multicast_frames_received = hw[PRESTERA_PORT_MC_PKTS_RCV_CNT];
947         st->frames_64_octets = hw[PRESTERA_PORT_PKTS_64L_CNT];
948         st->frames_65_to_127_octets = hw[PRESTERA_PORT_PKTS_65TO127L_CNT];
949         st->frames_128_to_255_octets = hw[PRESTERA_PORT_PKTS_128TO255L_CNT];
950         st->frames_256_to_511_octets = hw[PRESTERA_PORT_PKTS_256TO511L_CNT];
951         st->frames_512_to_1023_octets = hw[PRESTERA_PORT_PKTS_512TO1023L_CNT];
952         st->frames_1024_to_max_octets = hw[PRESTERA_PORT_PKTS_1024TOMAXL_CNT];
953         st->excessive_collision = hw[PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT];
954         st->multicast_frames_sent = hw[PRESTERA_PORT_MC_PKTS_SENT_CNT];
955         st->broadcast_frames_sent = hw[PRESTERA_PORT_BRDC_PKTS_SENT_CNT];
956         st->fc_sent = hw[PRESTERA_PORT_FC_SENT_CNT];
957         st->fc_received = hw[PRESTERA_PORT_GOOD_FC_RCV_CNT];
958         st->buffer_overrun = hw[PRESTERA_PORT_DROP_EVENTS_CNT];
959         st->undersize = hw[PRESTERA_PORT_UNDERSIZE_PKTS_CNT];
960         st->fragments = hw[PRESTERA_PORT_FRAGMENTS_PKTS_CNT];
961         st->oversize = hw[PRESTERA_PORT_OVERSIZE_PKTS_CNT];
962         st->jabber = hw[PRESTERA_PORT_JABBER_PKTS_CNT];
963         st->rx_error_frame_received = hw[PRESTERA_PORT_MAC_RCV_ERROR_CNT];
964         st->bad_crc = hw[PRESTERA_PORT_BAD_CRC_CNT];
965         st->collisions = hw[PRESTERA_PORT_COLLISIONS_CNT];
966         st->late_collision = hw[PRESTERA_PORT_LATE_COLLISIONS_CNT];
967         st->unicast_frames_received = hw[PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT];
968         st->unicast_frames_sent = hw[PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT];
969         st->sent_multiple = hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT];
970         st->sent_deferred = hw[PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT];
971         st->good_octets_sent = hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT];
972
973         return 0;
974 }
975
976 int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
977 {
978         struct prestera_msg_port_attr_req req = {
979                 .attr = PRESTERA_CMD_PORT_ATTR_LEARNING,
980                 .port = port->hw_id,
981                 .dev = port->dev_id,
982                 .param = {
983                         .learning = enable,
984                 }
985         };
986
987         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
988                             &req.cmd, sizeof(req));
989 }
990
991 int prestera_hw_port_flood_set(struct prestera_port *port, bool flood)
992 {
993         struct prestera_msg_port_attr_req req = {
994                 .attr = PRESTERA_CMD_PORT_ATTR_FLOOD,
995                 .port = port->hw_id,
996                 .dev = port->dev_id,
997                 .param = {
998                         .flood = flood,
999                 }
1000         };
1001
1002         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1003                             &req.cmd, sizeof(req));
1004 }
1005
1006 int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
1007 {
1008         struct prestera_msg_vlan_req req = {
1009                 .vid = vid,
1010         };
1011
1012         return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE,
1013                             &req.cmd, sizeof(req));
1014 }
1015
1016 int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid)
1017 {
1018         struct prestera_msg_vlan_req req = {
1019                 .vid = vid,
1020         };
1021
1022         return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE,
1023                             &req.cmd, sizeof(req));
1024 }
1025
1026 int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid,
1027                               bool is_member, bool untagged)
1028 {
1029         struct prestera_msg_vlan_req req = {
1030                 .port = port->hw_id,
1031                 .dev = port->dev_id,
1032                 .vid = vid,
1033                 .is_member = is_member,
1034                 .is_tagged = !untagged,
1035         };
1036
1037         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET,
1038                             &req.cmd, sizeof(req));
1039 }
1040
1041 int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid)
1042 {
1043         struct prestera_msg_vlan_req req = {
1044                 .port = port->hw_id,
1045                 .dev = port->dev_id,
1046                 .vid = vid,
1047         };
1048
1049         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET,
1050                             &req.cmd, sizeof(req));
1051 }
1052
1053 int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state)
1054 {
1055         struct prestera_msg_stp_req req = {
1056                 .port = port->hw_id,
1057                 .dev = port->dev_id,
1058                 .vid = vid,
1059                 .state = state,
1060         };
1061
1062         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET,
1063                             &req.cmd, sizeof(req));
1064 }
1065
1066 int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac,
1067                         u16 vid, bool dynamic)
1068 {
1069         struct prestera_msg_fdb_req req = {
1070                 .port = port->hw_id,
1071                 .dev = port->dev_id,
1072                 .vid = vid,
1073                 .dynamic = dynamic,
1074         };
1075
1076         ether_addr_copy(req.mac, mac);
1077
1078         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD,
1079                             &req.cmd, sizeof(req));
1080 }
1081
1082 int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac,
1083                         u16 vid)
1084 {
1085         struct prestera_msg_fdb_req req = {
1086                 .port = port->hw_id,
1087                 .dev = port->dev_id,
1088                 .vid = vid,
1089         };
1090
1091         ether_addr_copy(req.mac, mac);
1092
1093         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1094                             &req.cmd, sizeof(req));
1095 }
1096
1097 int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode)
1098 {
1099         struct prestera_msg_fdb_req req = {
1100                 .port = port->hw_id,
1101                 .dev = port->dev_id,
1102                 .flush_mode = mode,
1103         };
1104
1105         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1106                             &req.cmd, sizeof(req));
1107 }
1108
1109 int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode)
1110 {
1111         struct prestera_msg_fdb_req req = {
1112                 .vid = vid,
1113                 .flush_mode = mode,
1114         };
1115
1116         return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN,
1117                             &req.cmd, sizeof(req));
1118 }
1119
1120 int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
1121                                     u32 mode)
1122 {
1123         struct prestera_msg_fdb_req req = {
1124                 .port = port->hw_id,
1125                 .dev = port->dev_id,
1126                 .vid = vid,
1127                 .flush_mode = mode,
1128         };
1129
1130         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1131                             &req.cmd, sizeof(req));
1132 }
1133
1134 int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id)
1135 {
1136         struct prestera_msg_bridge_resp resp;
1137         struct prestera_msg_bridge_req req;
1138         int err;
1139
1140         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE,
1141                                &req.cmd, sizeof(req),
1142                                &resp.ret, sizeof(resp));
1143         if (err)
1144                 return err;
1145
1146         *bridge_id = resp.bridge;
1147
1148         return 0;
1149 }
1150
1151 int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id)
1152 {
1153         struct prestera_msg_bridge_req req = {
1154                 .bridge = bridge_id,
1155         };
1156
1157         return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE,
1158                             &req.cmd, sizeof(req));
1159 }
1160
1161 int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id)
1162 {
1163         struct prestera_msg_bridge_req req = {
1164                 .bridge = bridge_id,
1165                 .port = port->hw_id,
1166                 .dev = port->dev_id,
1167         };
1168
1169         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD,
1170                             &req.cmd, sizeof(req));
1171 }
1172
1173 int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)
1174 {
1175         struct prestera_msg_bridge_req req = {
1176                 .bridge = bridge_id,
1177                 .port = port->hw_id,
1178                 .dev = port->dev_id,
1179         };
1180
1181         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE,
1182                             &req.cmd, sizeof(req));
1183 }
1184
1185 int prestera_hw_rxtx_init(struct prestera_switch *sw,
1186                           struct prestera_rxtx_params *params)
1187 {
1188         struct prestera_msg_rxtx_resp resp;
1189         struct prestera_msg_rxtx_req req;
1190         int err;
1191
1192         req.use_sdma = params->use_sdma;
1193
1194         err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT,
1195                                &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1196         if (err)
1197                 return err;
1198
1199         params->map_addr = resp.map_addr;
1200
1201         return 0;
1202 }
1203
1204 int prestera_hw_rxtx_port_init(struct prestera_port *port)
1205 {
1206         struct prestera_msg_rxtx_port_req req = {
1207                 .port = port->hw_id,
1208                 .dev = port->dev_id,
1209         };
1210
1211         return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_RXTX_PORT_INIT,
1212                             &req.cmd, sizeof(req));
1213 }
1214
1215 int prestera_hw_event_handler_register(struct prestera_switch *sw,
1216                                        enum prestera_event_type type,
1217                                        prestera_event_cb_t fn,
1218                                        void *arg)
1219 {
1220         struct prestera_fw_event_handler *eh;
1221
1222         eh = __find_event_handler(sw, type);
1223         if (eh)
1224                 return -EEXIST;
1225
1226         eh = kmalloc(sizeof(*eh), GFP_KERNEL);
1227         if (!eh)
1228                 return -ENOMEM;
1229
1230         eh->type = type;
1231         eh->func = fn;
1232         eh->arg = arg;
1233
1234         INIT_LIST_HEAD(&eh->list);
1235
1236         list_add_rcu(&eh->list, &sw->event_handlers);
1237
1238         return 0;
1239 }
1240
1241 void prestera_hw_event_handler_unregister(struct prestera_switch *sw,
1242                                           enum prestera_event_type type,
1243                                           prestera_event_cb_t fn)
1244 {
1245         struct prestera_fw_event_handler *eh;
1246
1247         eh = __find_event_handler(sw, type);
1248         if (!eh)
1249                 return;
1250
1251         list_del_rcu(&eh->list);
1252         kfree_rcu(eh, rcu);
1253 }