mlxsw: Revert "Introduce initial XM router support"
[linux-2.6-block.git] / drivers / net / ethernet / mellanox / mlxsw / minimal.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2016-2019 Mellanox Technologies. All rights reserved */
3
4 #include <linux/netdevice.h>
5 #include <linux/etherdevice.h>
6 #include <linux/ethtool.h>
7 #include <linux/i2c.h>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/mod_devicetable.h>
11 #include <linux/types.h>
12
13 #include "core.h"
14 #include "core_env.h"
15 #include "i2c.h"
16
17 static const char mlxsw_m_driver_name[] = "mlxsw_minimal";
18
19 #define MLXSW_M_FWREV_MINOR     2000
20 #define MLXSW_M_FWREV_SUBMINOR  1886
21
22 static const struct mlxsw_fw_rev mlxsw_m_fw_rev = {
23         .minor = MLXSW_M_FWREV_MINOR,
24         .subminor = MLXSW_M_FWREV_SUBMINOR,
25 };
26
27 struct mlxsw_m_port;
28
29 struct mlxsw_m {
30         struct mlxsw_m_port **ports;
31         int *module_to_port;
32         struct mlxsw_core *core;
33         const struct mlxsw_bus_info *bus_info;
34         u8 base_mac[ETH_ALEN];
35         u8 max_ports;
36 };
37
38 struct mlxsw_m_port {
39         struct net_device *dev;
40         struct mlxsw_m *mlxsw_m;
41         u16 local_port;
42         u8 module;
43 };
44
45 static int mlxsw_m_base_mac_get(struct mlxsw_m *mlxsw_m)
46 {
47         char spad_pl[MLXSW_REG_SPAD_LEN] = {0};
48         int err;
49
50         err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(spad), spad_pl);
51         if (err)
52                 return err;
53         mlxsw_reg_spad_base_mac_memcpy_from(spad_pl, mlxsw_m->base_mac);
54         return 0;
55 }
56
57 static int mlxsw_m_port_open(struct net_device *dev)
58 {
59         struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev);
60         struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m;
61
62         return mlxsw_env_module_port_up(mlxsw_m->core, 0,
63                                         mlxsw_m_port->module);
64 }
65
66 static int mlxsw_m_port_stop(struct net_device *dev)
67 {
68         struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev);
69         struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m;
70
71         mlxsw_env_module_port_down(mlxsw_m->core, 0, mlxsw_m_port->module);
72         return 0;
73 }
74
75 static struct devlink_port *
76 mlxsw_m_port_get_devlink_port(struct net_device *dev)
77 {
78         struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev);
79         struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m;
80
81         return mlxsw_core_port_devlink_port_get(mlxsw_m->core,
82                                                 mlxsw_m_port->local_port);
83 }
84
85 static const struct net_device_ops mlxsw_m_port_netdev_ops = {
86         .ndo_open               = mlxsw_m_port_open,
87         .ndo_stop               = mlxsw_m_port_stop,
88         .ndo_get_devlink_port   = mlxsw_m_port_get_devlink_port,
89 };
90
91 static void mlxsw_m_module_get_drvinfo(struct net_device *dev,
92                                        struct ethtool_drvinfo *drvinfo)
93 {
94         struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev);
95         struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m;
96
97         strlcpy(drvinfo->driver, mlxsw_m->bus_info->device_kind,
98                 sizeof(drvinfo->driver));
99         snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
100                  "%d.%d.%d",
101                  mlxsw_m->bus_info->fw_rev.major,
102                  mlxsw_m->bus_info->fw_rev.minor,
103                  mlxsw_m->bus_info->fw_rev.subminor);
104         strlcpy(drvinfo->bus_info, mlxsw_m->bus_info->device_name,
105                 sizeof(drvinfo->bus_info));
106 }
107
108 static int mlxsw_m_get_module_info(struct net_device *netdev,
109                                    struct ethtool_modinfo *modinfo)
110 {
111         struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
112         struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
113
114         return mlxsw_env_get_module_info(netdev, core, 0, mlxsw_m_port->module,
115                                          modinfo);
116 }
117
118 static int
119 mlxsw_m_get_module_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee,
120                           u8 *data)
121 {
122         struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
123         struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
124
125         return mlxsw_env_get_module_eeprom(netdev, core, 0,
126                                            mlxsw_m_port->module, ee, data);
127 }
128
129 static int
130 mlxsw_m_get_module_eeprom_by_page(struct net_device *netdev,
131                                   const struct ethtool_module_eeprom *page,
132                                   struct netlink_ext_ack *extack)
133 {
134         struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
135         struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
136
137         return mlxsw_env_get_module_eeprom_by_page(core, 0,
138                                                    mlxsw_m_port->module,
139                                                    page, extack);
140 }
141
142 static int mlxsw_m_reset(struct net_device *netdev, u32 *flags)
143 {
144         struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
145         struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
146
147         return mlxsw_env_reset_module(netdev, core, 0, mlxsw_m_port->module,
148                                       flags);
149 }
150
151 static int
152 mlxsw_m_get_module_power_mode(struct net_device *netdev,
153                               struct ethtool_module_power_mode_params *params,
154                               struct netlink_ext_ack *extack)
155 {
156         struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
157         struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
158
159         return mlxsw_env_get_module_power_mode(core, 0, mlxsw_m_port->module,
160                                                params, extack);
161 }
162
163 static int
164 mlxsw_m_set_module_power_mode(struct net_device *netdev,
165                               const struct ethtool_module_power_mode_params *params,
166                               struct netlink_ext_ack *extack)
167 {
168         struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
169         struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
170
171         return mlxsw_env_set_module_power_mode(core, 0, mlxsw_m_port->module,
172                                                params->policy, extack);
173 }
174
175 static const struct ethtool_ops mlxsw_m_port_ethtool_ops = {
176         .get_drvinfo            = mlxsw_m_module_get_drvinfo,
177         .get_module_info        = mlxsw_m_get_module_info,
178         .get_module_eeprom      = mlxsw_m_get_module_eeprom,
179         .get_module_eeprom_by_page = mlxsw_m_get_module_eeprom_by_page,
180         .reset                  = mlxsw_m_reset,
181         .get_module_power_mode  = mlxsw_m_get_module_power_mode,
182         .set_module_power_mode  = mlxsw_m_set_module_power_mode,
183 };
184
185 static int
186 mlxsw_m_port_module_info_get(struct mlxsw_m *mlxsw_m, u16 local_port,
187                              u8 *p_module, u8 *p_width)
188 {
189         char pmlp_pl[MLXSW_REG_PMLP_LEN];
190         int err;
191
192         mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
193         err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(pmlp), pmlp_pl);
194         if (err)
195                 return err;
196         *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
197         *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl);
198
199         return 0;
200 }
201
202 static int
203 mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port)
204 {
205         struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m;
206         char ppad_pl[MLXSW_REG_PPAD_LEN];
207         u8 addr[ETH_ALEN];
208         int err;
209
210         mlxsw_reg_ppad_pack(ppad_pl, false, 0);
211         err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(ppad), ppad_pl);
212         if (err)
213                 return err;
214         mlxsw_reg_ppad_mac_memcpy_from(ppad_pl, addr);
215         eth_hw_addr_gen(mlxsw_m_port->dev, addr, mlxsw_m_port->module + 1);
216         return 0;
217 }
218
219 static int
220 mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 module)
221 {
222         struct mlxsw_m_port *mlxsw_m_port;
223         struct net_device *dev;
224         int err;
225
226         err = mlxsw_core_port_init(mlxsw_m->core, local_port, 0,
227                                    module + 1, false, 0, false,
228                                    0, mlxsw_m->base_mac,
229                                    sizeof(mlxsw_m->base_mac));
230         if (err) {
231                 dev_err(mlxsw_m->bus_info->dev, "Port %d: Failed to init core port\n",
232                         local_port);
233                 return err;
234         }
235
236         dev = alloc_etherdev(sizeof(struct mlxsw_m_port));
237         if (!dev) {
238                 err = -ENOMEM;
239                 goto err_alloc_etherdev;
240         }
241
242         SET_NETDEV_DEV(dev, mlxsw_m->bus_info->dev);
243         dev_net_set(dev, mlxsw_core_net(mlxsw_m->core));
244         mlxsw_m_port = netdev_priv(dev);
245         mlxsw_m_port->dev = dev;
246         mlxsw_m_port->mlxsw_m = mlxsw_m;
247         mlxsw_m_port->local_port = local_port;
248         mlxsw_m_port->module = module;
249
250         dev->netdev_ops = &mlxsw_m_port_netdev_ops;
251         dev->ethtool_ops = &mlxsw_m_port_ethtool_ops;
252
253         err = mlxsw_m_port_dev_addr_get(mlxsw_m_port);
254         if (err) {
255                 dev_err(mlxsw_m->bus_info->dev, "Port %d: Unable to get port mac address\n",
256                         mlxsw_m_port->local_port);
257                 goto err_dev_addr_get;
258         }
259
260         netif_carrier_off(dev);
261         mlxsw_m->ports[local_port] = mlxsw_m_port;
262         err = register_netdev(dev);
263         if (err) {
264                 dev_err(mlxsw_m->bus_info->dev, "Port %d: Failed to register netdev\n",
265                         mlxsw_m_port->local_port);
266                 goto err_register_netdev;
267         }
268
269         mlxsw_core_port_eth_set(mlxsw_m->core, mlxsw_m_port->local_port,
270                                 mlxsw_m_port, dev);
271
272         return 0;
273
274 err_register_netdev:
275         mlxsw_m->ports[local_port] = NULL;
276 err_dev_addr_get:
277         free_netdev(dev);
278 err_alloc_etherdev:
279         mlxsw_core_port_fini(mlxsw_m->core, local_port);
280         return err;
281 }
282
283 static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u16 local_port)
284 {
285         struct mlxsw_m_port *mlxsw_m_port = mlxsw_m->ports[local_port];
286
287         mlxsw_core_port_clear(mlxsw_m->core, local_port, mlxsw_m);
288         unregister_netdev(mlxsw_m_port->dev); /* This calls ndo_stop */
289         mlxsw_m->ports[local_port] = NULL;
290         free_netdev(mlxsw_m_port->dev);
291         mlxsw_core_port_fini(mlxsw_m->core, local_port);
292 }
293
294 static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u16 local_port,
295                                    u8 *last_module)
296 {
297         unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core);
298         u8 module, width;
299         int err;
300
301         /* Fill out to local port mapping array */
302         err = mlxsw_m_port_module_info_get(mlxsw_m, local_port, &module,
303                                            &width);
304         if (err)
305                 return err;
306
307         if (!width)
308                 return 0;
309         /* Skip, if port belongs to the cluster */
310         if (module == *last_module)
311                 return 0;
312         *last_module = module;
313
314         if (WARN_ON_ONCE(module >= max_ports))
315                 return -EINVAL;
316         mlxsw_env_module_port_map(mlxsw_m->core, 0, module);
317         mlxsw_m->module_to_port[module] = ++mlxsw_m->max_ports;
318
319         return 0;
320 }
321
322 static void mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 module)
323 {
324         mlxsw_m->module_to_port[module] = -1;
325         mlxsw_env_module_port_unmap(mlxsw_m->core, 0, module);
326 }
327
328 static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m)
329 {
330         unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core);
331         struct devlink *devlink = priv_to_devlink(mlxsw_m->core);
332         u8 last_module = max_ports;
333         int i;
334         int err;
335
336         mlxsw_m->ports = kcalloc(max_ports, sizeof(*mlxsw_m->ports),
337                                  GFP_KERNEL);
338         if (!mlxsw_m->ports)
339                 return -ENOMEM;
340
341         mlxsw_m->module_to_port = kmalloc_array(max_ports, sizeof(int),
342                                                 GFP_KERNEL);
343         if (!mlxsw_m->module_to_port) {
344                 err = -ENOMEM;
345                 goto err_module_to_port_alloc;
346         }
347
348         /* Invalidate the entries of module to local port mapping array */
349         for (i = 0; i < max_ports; i++)
350                 mlxsw_m->module_to_port[i] = -1;
351
352         /* Fill out module to local port mapping array */
353         for (i = 1; i < max_ports; i++) {
354                 err = mlxsw_m_port_module_map(mlxsw_m, i, &last_module);
355                 if (err)
356                         goto err_module_to_port_map;
357         }
358
359         /* Create port objects for each valid entry */
360         devl_lock(devlink);
361         for (i = 0; i < mlxsw_m->max_ports; i++) {
362                 if (mlxsw_m->module_to_port[i] > 0) {
363                         err = mlxsw_m_port_create(mlxsw_m,
364                                                   mlxsw_m->module_to_port[i],
365                                                   i);
366                         if (err)
367                                 goto err_module_to_port_create;
368                 }
369         }
370         devl_unlock(devlink);
371
372         return 0;
373
374 err_module_to_port_create:
375         for (i--; i >= 0; i--) {
376                 if (mlxsw_m->module_to_port[i] > 0)
377                         mlxsw_m_port_remove(mlxsw_m,
378                                             mlxsw_m->module_to_port[i]);
379         }
380         devl_unlock(devlink);
381         i = max_ports;
382 err_module_to_port_map:
383         for (i--; i > 0; i--)
384                 mlxsw_m_port_module_unmap(mlxsw_m, i);
385         kfree(mlxsw_m->module_to_port);
386 err_module_to_port_alloc:
387         kfree(mlxsw_m->ports);
388         return err;
389 }
390
391 static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m)
392 {
393         struct devlink *devlink = priv_to_devlink(mlxsw_m->core);
394         int i;
395
396         devl_lock(devlink);
397         for (i = 0; i < mlxsw_m->max_ports; i++) {
398                 if (mlxsw_m->module_to_port[i] > 0) {
399                         mlxsw_m_port_remove(mlxsw_m,
400                                             mlxsw_m->module_to_port[i]);
401                         mlxsw_m_port_module_unmap(mlxsw_m, i);
402                 }
403         }
404         devl_unlock(devlink);
405
406         kfree(mlxsw_m->module_to_port);
407         kfree(mlxsw_m->ports);
408 }
409
410 static int mlxsw_m_fw_rev_validate(struct mlxsw_m *mlxsw_m)
411 {
412         const struct mlxsw_fw_rev *rev = &mlxsw_m->bus_info->fw_rev;
413
414         /* Validate driver and FW are compatible.
415          * Do not check major version, since it defines chip type, while
416          * driver is supposed to support any type.
417          */
418         if (mlxsw_core_fw_rev_minor_subminor_validate(rev, &mlxsw_m_fw_rev))
419                 return 0;
420
421         dev_err(mlxsw_m->bus_info->dev, "The firmware version %d.%d.%d is incompatible with the driver (required >= %d.%d.%d)\n",
422                 rev->major, rev->minor, rev->subminor, rev->major,
423                 mlxsw_m_fw_rev.minor, mlxsw_m_fw_rev.subminor);
424
425         return -EINVAL;
426 }
427
428 static int mlxsw_m_init(struct mlxsw_core *mlxsw_core,
429                         const struct mlxsw_bus_info *mlxsw_bus_info,
430                         struct netlink_ext_ack *extack)
431 {
432         struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core);
433         int err;
434
435         mlxsw_m->core = mlxsw_core;
436         mlxsw_m->bus_info = mlxsw_bus_info;
437
438         err = mlxsw_m_fw_rev_validate(mlxsw_m);
439         if (err)
440                 return err;
441
442         err = mlxsw_m_base_mac_get(mlxsw_m);
443         if (err) {
444                 dev_err(mlxsw_m->bus_info->dev, "Failed to get base mac\n");
445                 return err;
446         }
447
448         err = mlxsw_m_ports_create(mlxsw_m);
449         if (err) {
450                 dev_err(mlxsw_m->bus_info->dev, "Failed to create ports\n");
451                 return err;
452         }
453
454         return 0;
455 }
456
457 static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core)
458 {
459         struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core);
460
461         mlxsw_m_ports_remove(mlxsw_m);
462 }
463
464 static const struct mlxsw_config_profile mlxsw_m_config_profile;
465
466 static struct mlxsw_driver mlxsw_m_driver = {
467         .kind                   = mlxsw_m_driver_name,
468         .priv_size              = sizeof(struct mlxsw_m),
469         .init                   = mlxsw_m_init,
470         .fini                   = mlxsw_m_fini,
471         .profile                = &mlxsw_m_config_profile,
472 };
473
474 static const struct i2c_device_id mlxsw_m_i2c_id[] = {
475         { "mlxsw_minimal", 0},
476         { },
477 };
478
479 static struct i2c_driver mlxsw_m_i2c_driver = {
480         .driver.name = "mlxsw_minimal",
481         .class = I2C_CLASS_HWMON,
482         .id_table = mlxsw_m_i2c_id,
483 };
484
485 static int __init mlxsw_m_module_init(void)
486 {
487         int err;
488
489         err = mlxsw_core_driver_register(&mlxsw_m_driver);
490         if (err)
491                 return err;
492
493         err = mlxsw_i2c_driver_register(&mlxsw_m_i2c_driver);
494         if (err)
495                 goto err_i2c_driver_register;
496
497         return 0;
498
499 err_i2c_driver_register:
500         mlxsw_core_driver_unregister(&mlxsw_m_driver);
501
502         return err;
503 }
504
505 static void __exit mlxsw_m_module_exit(void)
506 {
507         mlxsw_i2c_driver_unregister(&mlxsw_m_i2c_driver);
508         mlxsw_core_driver_unregister(&mlxsw_m_driver);
509 }
510
511 module_init(mlxsw_m_module_init);
512 module_exit(mlxsw_m_module_exit);
513
514 MODULE_LICENSE("Dual BSD/GPL");
515 MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
516 MODULE_DESCRIPTION("Mellanox minimal driver");
517 MODULE_DEVICE_TABLE(i2c, mlxsw_m_i2c_id);