]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/net/ethernet/marvell/prestera/prestera_main.c
net: marvell: prestera: Add ethtool interface support
[mirror_ubuntu-jammy-kernel.git] / drivers / net / ethernet / marvell / prestera / prestera_main.c
CommitLineData
501ef306
VK
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/jiffies.h>
6#include <linux/list.h>
7#include <linux/module.h>
8#include <linux/netdev_features.h>
9#include <linux/of.h>
10#include <linux/of_net.h>
11
12#include "prestera.h"
13#include "prestera_hw.h"
14#include "prestera_rxtx.h"
34dd1710 15#include "prestera_devlink.h"
a97d3c69 16#include "prestera_ethtool.h"
501ef306
VK
17
18#define PRESTERA_MTU_DEFAULT 1536
19
20#define PRESTERA_STATS_DELAY_MS 1000
21
22#define PRESTERA_MAC_ADDR_NUM_MAX 255
23
24static struct workqueue_struct *prestera_wq;
25
26struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw,
27 u32 dev_id, u32 hw_id)
28{
29 struct prestera_port *port = NULL;
30
31 read_lock(&sw->port_list_lock);
32 list_for_each_entry(port, &sw->port_list, list) {
33 if (port->dev_id == dev_id && port->hw_id == hw_id)
34 break;
35 }
36 read_unlock(&sw->port_list_lock);
37
38 return port;
39}
40
41static struct prestera_port *prestera_find_port(struct prestera_switch *sw,
42 u32 id)
43{
44 struct prestera_port *port = NULL;
45
46 read_lock(&sw->port_list_lock);
47 list_for_each_entry(port, &sw->port_list, list) {
48 if (port->id == id)
49 break;
50 }
51 read_unlock(&sw->port_list_lock);
52
53 return port;
54}
55
56static int prestera_port_open(struct net_device *dev)
57{
58 struct prestera_port *port = netdev_priv(dev);
59 int err;
60
61 err = prestera_hw_port_state_set(port, true);
62 if (err)
63 return err;
64
65 netif_start_queue(dev);
66
67 return 0;
68}
69
70static int prestera_port_close(struct net_device *dev)
71{
72 struct prestera_port *port = netdev_priv(dev);
73 int err;
74
75 netif_stop_queue(dev);
76
77 err = prestera_hw_port_state_set(port, false);
78 if (err)
79 return err;
80
81 return 0;
82}
83
84static netdev_tx_t prestera_port_xmit(struct sk_buff *skb,
85 struct net_device *dev)
86{
87 return prestera_rxtx_xmit(netdev_priv(dev), skb);
88}
89
90static int prestera_is_valid_mac_addr(struct prestera_port *port, u8 *addr)
91{
92 if (!is_valid_ether_addr(addr))
93 return -EADDRNOTAVAIL;
94
95 /* firmware requires that port's MAC address contains first 5 bytes
96 * of the base MAC address
97 */
98 if (memcmp(port->sw->base_mac, addr, ETH_ALEN - 1))
99 return -EINVAL;
100
101 return 0;
102}
103
104static int prestera_port_set_mac_address(struct net_device *dev, void *p)
105{
106 struct prestera_port *port = netdev_priv(dev);
107 struct sockaddr *addr = p;
108 int err;
109
110 err = prestera_is_valid_mac_addr(port, addr->sa_data);
111 if (err)
112 return err;
113
114 err = prestera_hw_port_mac_set(port, addr->sa_data);
115 if (err)
116 return err;
117
118 ether_addr_copy(dev->dev_addr, addr->sa_data);
119
120 return 0;
121}
122
123static int prestera_port_change_mtu(struct net_device *dev, int mtu)
124{
125 struct prestera_port *port = netdev_priv(dev);
126 int err;
127
128 err = prestera_hw_port_mtu_set(port, mtu);
129 if (err)
130 return err;
131
132 dev->mtu = mtu;
133
134 return 0;
135}
136
137static void prestera_port_get_stats64(struct net_device *dev,
138 struct rtnl_link_stats64 *stats)
139{
140 struct prestera_port *port = netdev_priv(dev);
141 struct prestera_port_stats *port_stats = &port->cached_hw_stats.stats;
142
143 stats->rx_packets = port_stats->broadcast_frames_received +
144 port_stats->multicast_frames_received +
145 port_stats->unicast_frames_received;
146
147 stats->tx_packets = port_stats->broadcast_frames_sent +
148 port_stats->multicast_frames_sent +
149 port_stats->unicast_frames_sent;
150
151 stats->rx_bytes = port_stats->good_octets_received;
152
153 stats->tx_bytes = port_stats->good_octets_sent;
154
155 stats->rx_errors = port_stats->rx_error_frame_received;
156 stats->tx_errors = port_stats->mac_trans_error;
157
158 stats->rx_dropped = port_stats->buffer_overrun;
159 stats->tx_dropped = 0;
160
161 stats->multicast = port_stats->multicast_frames_received;
162 stats->collisions = port_stats->excessive_collision;
163
164 stats->rx_crc_errors = port_stats->bad_crc;
165}
166
167static void prestera_port_get_hw_stats(struct prestera_port *port)
168{
169 prestera_hw_port_stats_get(port, &port->cached_hw_stats.stats);
170}
171
172static void prestera_port_stats_update(struct work_struct *work)
173{
174 struct prestera_port *port =
175 container_of(work, struct prestera_port,
176 cached_hw_stats.caching_dw.work);
177
178 prestera_port_get_hw_stats(port);
179
180 queue_delayed_work(prestera_wq, &port->cached_hw_stats.caching_dw,
181 msecs_to_jiffies(PRESTERA_STATS_DELAY_MS));
182}
183
184static const struct net_device_ops prestera_netdev_ops = {
185 .ndo_open = prestera_port_open,
186 .ndo_stop = prestera_port_close,
187 .ndo_start_xmit = prestera_port_xmit,
188 .ndo_change_mtu = prestera_port_change_mtu,
189 .ndo_get_stats64 = prestera_port_get_stats64,
190 .ndo_set_mac_address = prestera_port_set_mac_address,
34dd1710 191 .ndo_get_devlink_port = prestera_devlink_get_port,
501ef306
VK
192};
193
a97d3c69
VK
194int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
195 u64 adver_link_modes, u8 adver_fec)
501ef306
VK
196{
197 bool refresh = false;
a97d3c69 198 u64 link_modes;
501ef306 199 int err;
a97d3c69 200 u8 fec;
501ef306
VK
201
202 if (port->caps.type != PRESTERA_PORT_TYPE_TP)
203 return enable ? -EINVAL : 0;
204
a97d3c69
VK
205 if (!enable)
206 goto set_autoneg;
207
208 link_modes = port->caps.supp_link_modes & adver_link_modes;
209 fec = port->caps.supp_fec & adver_fec;
210
211 if (!link_modes && !fec)
212 return -EOPNOTSUPP;
213
214 if (link_modes && port->adver_link_modes != link_modes) {
501ef306
VK
215 port->adver_link_modes = link_modes;
216 refresh = true;
217 }
218
a97d3c69
VK
219 if (fec && port->adver_fec != fec) {
220 port->adver_fec = fec;
221 refresh = true;
222 }
223
224set_autoneg:
225 if (port->autoneg == enable && !refresh)
501ef306
VK
226 return 0;
227
228 err = prestera_hw_port_autoneg_set(port, enable, port->adver_link_modes,
229 port->adver_fec);
230 if (err)
231 return err;
232
233 port->autoneg = enable;
234
235 return 0;
236}
237
238static void prestera_port_list_add(struct prestera_port *port)
239{
240 write_lock(&port->sw->port_list_lock);
241 list_add(&port->list, &port->sw->port_list);
242 write_unlock(&port->sw->port_list_lock);
243}
244
245static void prestera_port_list_del(struct prestera_port *port)
246{
247 write_lock(&port->sw->port_list_lock);
248 list_del(&port->list);
249 write_unlock(&port->sw->port_list_lock);
250}
251
252static int prestera_port_create(struct prestera_switch *sw, u32 id)
253{
254 struct prestera_port *port;
255 struct net_device *dev;
256 int err;
257
258 dev = alloc_etherdev(sizeof(*port));
259 if (!dev)
260 return -ENOMEM;
261
262 port = netdev_priv(dev);
263
264 port->dev = dev;
265 port->id = id;
266 port->sw = sw;
267
268 err = prestera_hw_port_info_get(port, &port->dev_id, &port->hw_id,
269 &port->fp_id);
270 if (err) {
271 dev_err(prestera_dev(sw), "Failed to get port(%u) info\n", id);
34dd1710 272 goto err_port_info_get;
501ef306
VK
273 }
274
34dd1710
VK
275 err = prestera_devlink_port_register(port);
276 if (err)
277 goto err_dl_port_register;
278
501ef306
VK
279 dev->features |= NETIF_F_NETNS_LOCAL;
280 dev->netdev_ops = &prestera_netdev_ops;
a97d3c69 281 dev->ethtool_ops = &prestera_ethtool_ops;
501ef306
VK
282
283 netif_carrier_off(dev);
284
285 dev->mtu = min_t(unsigned int, sw->mtu_max, PRESTERA_MTU_DEFAULT);
286 dev->min_mtu = sw->mtu_min;
287 dev->max_mtu = sw->mtu_max;
288
289 err = prestera_hw_port_mtu_set(port, dev->mtu);
290 if (err) {
291 dev_err(prestera_dev(sw), "Failed to set port(%u) mtu(%d)\n",
292 id, dev->mtu);
293 goto err_port_init;
294 }
295
296 if (port->fp_id >= PRESTERA_MAC_ADDR_NUM_MAX)
297 goto err_port_init;
298
299 /* firmware requires that port's MAC address consist of the first
300 * 5 bytes of the base MAC address
301 */
302 memcpy(dev->dev_addr, sw->base_mac, dev->addr_len - 1);
303 dev->dev_addr[dev->addr_len - 1] = port->fp_id;
304
305 err = prestera_hw_port_mac_set(port, dev->dev_addr);
306 if (err) {
307 dev_err(prestera_dev(sw), "Failed to set port(%u) mac addr\n", id);
308 goto err_port_init;
309 }
310
311 err = prestera_hw_port_cap_get(port, &port->caps);
312 if (err) {
313 dev_err(prestera_dev(sw), "Failed to get port(%u) caps\n", id);
314 goto err_port_init;
315 }
316
317 port->adver_fec = BIT(PRESTERA_PORT_FEC_OFF);
318 prestera_port_autoneg_set(port, true, port->caps.supp_link_modes,
319 port->caps.supp_fec);
320
321 err = prestera_hw_port_state_set(port, false);
322 if (err) {
323 dev_err(prestera_dev(sw), "Failed to set port(%u) down\n", id);
324 goto err_port_init;
325 }
326
327 err = prestera_rxtx_port_init(port);
328 if (err)
329 goto err_port_init;
330
331 INIT_DELAYED_WORK(&port->cached_hw_stats.caching_dw,
332 &prestera_port_stats_update);
333
334 prestera_port_list_add(port);
335
336 err = register_netdev(dev);
337 if (err)
338 goto err_register_netdev;
339
34dd1710
VK
340 prestera_devlink_port_set(port);
341
501ef306
VK
342 return 0;
343
344err_register_netdev:
345 prestera_port_list_del(port);
346err_port_init:
34dd1710
VK
347 prestera_devlink_port_unregister(port);
348err_dl_port_register:
349err_port_info_get:
501ef306
VK
350 free_netdev(dev);
351 return err;
352}
353
354static void prestera_port_destroy(struct prestera_port *port)
355{
356 struct net_device *dev = port->dev;
357
358 cancel_delayed_work_sync(&port->cached_hw_stats.caching_dw);
34dd1710 359 prestera_devlink_port_clear(port);
501ef306
VK
360 unregister_netdev(dev);
361 prestera_port_list_del(port);
34dd1710 362 prestera_devlink_port_unregister(port);
501ef306
VK
363 free_netdev(dev);
364}
365
366static void prestera_destroy_ports(struct prestera_switch *sw)
367{
368 struct prestera_port *port, *tmp;
369
370 list_for_each_entry_safe(port, tmp, &sw->port_list, list)
371 prestera_port_destroy(port);
372}
373
374static int prestera_create_ports(struct prestera_switch *sw)
375{
376 struct prestera_port *port, *tmp;
377 u32 port_idx;
378 int err;
379
380 for (port_idx = 0; port_idx < sw->port_count; port_idx++) {
381 err = prestera_port_create(sw, port_idx);
382 if (err)
383 goto err_port_create;
384 }
385
386 return 0;
387
388err_port_create:
389 list_for_each_entry_safe(port, tmp, &sw->port_list, list)
390 prestera_port_destroy(port);
391
392 return err;
393}
394
395static void prestera_port_handle_event(struct prestera_switch *sw,
396 struct prestera_event *evt, void *arg)
397{
398 struct delayed_work *caching_dw;
399 struct prestera_port *port;
400
401 port = prestera_find_port(sw, evt->port_evt.port_id);
402 if (!port || !port->dev)
403 return;
404
405 caching_dw = &port->cached_hw_stats.caching_dw;
406
407 if (evt->id == PRESTERA_PORT_EVENT_STATE_CHANGED) {
408 if (evt->port_evt.data.oper_state) {
409 netif_carrier_on(port->dev);
410 if (!delayed_work_pending(caching_dw))
411 queue_delayed_work(prestera_wq, caching_dw, 0);
412 } else {
413 netif_carrier_off(port->dev);
414 if (delayed_work_pending(caching_dw))
415 cancel_delayed_work(caching_dw);
416 }
417 }
418}
419
420static int prestera_event_handlers_register(struct prestera_switch *sw)
421{
422 return prestera_hw_event_handler_register(sw, PRESTERA_EVENT_TYPE_PORT,
423 prestera_port_handle_event,
424 NULL);
425}
426
427static void prestera_event_handlers_unregister(struct prestera_switch *sw)
428{
429 prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_PORT,
430 prestera_port_handle_event);
431}
432
433static int prestera_switch_set_base_mac_addr(struct prestera_switch *sw)
434{
435 struct device_node *base_mac_np;
436 struct device_node *np;
437 const char *base_mac;
438
439 np = of_find_compatible_node(NULL, NULL, "marvell,prestera");
440 base_mac_np = of_parse_phandle(np, "base-mac-provider", 0);
441
442 base_mac = of_get_mac_address(base_mac_np);
443 of_node_put(base_mac_np);
444 if (!IS_ERR(base_mac))
445 ether_addr_copy(sw->base_mac, base_mac);
446
447 if (!is_valid_ether_addr(sw->base_mac)) {
448 eth_random_addr(sw->base_mac);
449 dev_info(prestera_dev(sw), "using random base mac address\n");
450 }
451
452 return prestera_hw_switch_mac_set(sw, sw->base_mac);
453}
454
455static int prestera_switch_init(struct prestera_switch *sw)
456{
457 int err;
458
459 err = prestera_hw_switch_init(sw);
460 if (err) {
461 dev_err(prestera_dev(sw), "Failed to init Switch device\n");
462 return err;
463 }
464
465 rwlock_init(&sw->port_list_lock);
466 INIT_LIST_HEAD(&sw->port_list);
467
468 err = prestera_switch_set_base_mac_addr(sw);
469 if (err)
470 return err;
471
472 err = prestera_rxtx_switch_init(sw);
473 if (err)
474 return err;
475
476 err = prestera_event_handlers_register(sw);
477 if (err)
478 goto err_handlers_register;
479
34dd1710
VK
480 err = prestera_devlink_register(sw);
481 if (err)
482 goto err_dl_register;
483
501ef306
VK
484 err = prestera_create_ports(sw);
485 if (err)
486 goto err_ports_create;
487
488 return 0;
489
490err_ports_create:
34dd1710
VK
491 prestera_devlink_unregister(sw);
492err_dl_register:
501ef306
VK
493 prestera_event_handlers_unregister(sw);
494err_handlers_register:
495 prestera_rxtx_switch_fini(sw);
496 prestera_hw_switch_fini(sw);
497
498 return err;
499}
500
501static void prestera_switch_fini(struct prestera_switch *sw)
502{
503 prestera_destroy_ports(sw);
34dd1710 504 prestera_devlink_unregister(sw);
501ef306
VK
505 prestera_event_handlers_unregister(sw);
506 prestera_rxtx_switch_fini(sw);
507 prestera_hw_switch_fini(sw);
508}
509
510int prestera_device_register(struct prestera_device *dev)
511{
512 struct prestera_switch *sw;
513 int err;
514
34dd1710 515 sw = prestera_devlink_alloc();
501ef306
VK
516 if (!sw)
517 return -ENOMEM;
518
519 dev->priv = sw;
520 sw->dev = dev;
521
522 err = prestera_switch_init(sw);
523 if (err) {
34dd1710 524 prestera_devlink_free(sw);
501ef306
VK
525 return err;
526 }
527
528 return 0;
529}
530EXPORT_SYMBOL(prestera_device_register);
531
532void prestera_device_unregister(struct prestera_device *dev)
533{
534 struct prestera_switch *sw = dev->priv;
535
536 prestera_switch_fini(sw);
34dd1710 537 prestera_devlink_free(sw);
501ef306
VK
538}
539EXPORT_SYMBOL(prestera_device_unregister);
540
541static int __init prestera_module_init(void)
542{
543 prestera_wq = alloc_workqueue("prestera", 0, 0);
544 if (!prestera_wq)
545 return -ENOMEM;
546
547 return 0;
548}
549
550static void __exit prestera_module_exit(void)
551{
552 destroy_workqueue(prestera_wq);
553}
554
555module_init(prestera_module_init);
556module_exit(prestera_module_exit);
557
558MODULE_LICENSE("Dual BSD/GPL");
559MODULE_DESCRIPTION("Marvell Prestera switch driver");