hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/net/dsa/dsa.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * net/dsa/dsa.c - Hardware switch handling
34 * Copyright (c) 2008-2009 Marvell Semiconductor
45 * Copyright (c) 2013 Florian Fainelli <florian@openwrt.org>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
106 */
117
128 #include <linux/device.h>
....@@ -27,6 +23,9 @@
2723
2824 #include "dsa_priv.h"
2925
26
+static LIST_HEAD(dsa_tag_drivers_list);
27
+static DEFINE_MUTEX(dsa_tag_drivers_lock);
28
+
3029 static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff *skb,
3130 struct net_device *dev)
3231 {
....@@ -35,53 +34,97 @@
3534 }
3635
3736 static const struct dsa_device_ops none_ops = {
37
+ .name = "none",
38
+ .proto = DSA_TAG_PROTO_NONE,
3839 .xmit = dsa_slave_notag_xmit,
3940 .rcv = NULL,
4041 };
4142
42
-const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = {
43
-#ifdef CONFIG_NET_DSA_TAG_BRCM
44
- [DSA_TAG_PROTO_BRCM] = &brcm_netdev_ops,
45
-#endif
46
-#ifdef CONFIG_NET_DSA_TAG_BRCM_PREPEND
47
- [DSA_TAG_PROTO_BRCM_PREPEND] = &brcm_prepend_netdev_ops,
48
-#endif
49
-#ifdef CONFIG_NET_DSA_TAG_DSA
50
- [DSA_TAG_PROTO_DSA] = &dsa_netdev_ops,
51
-#endif
52
-#ifdef CONFIG_NET_DSA_TAG_EDSA
53
- [DSA_TAG_PROTO_EDSA] = &edsa_netdev_ops,
54
-#endif
55
-#ifdef CONFIG_NET_DSA_TAG_KSZ
56
- [DSA_TAG_PROTO_KSZ] = &ksz_netdev_ops,
57
-#endif
58
-#ifdef CONFIG_NET_DSA_TAG_LAN9303
59
- [DSA_TAG_PROTO_LAN9303] = &lan9303_netdev_ops,
60
-#endif
61
-#ifdef CONFIG_NET_DSA_TAG_MTK
62
- [DSA_TAG_PROTO_MTK] = &mtk_netdev_ops,
63
-#endif
64
-#ifdef CONFIG_NET_DSA_TAG_QCA
65
- [DSA_TAG_PROTO_QCA] = &qca_netdev_ops,
66
-#endif
67
-#ifdef CONFIG_NET_DSA_TAG_TRAILER
68
- [DSA_TAG_PROTO_TRAILER] = &trailer_netdev_ops,
69
-#endif
70
- [DSA_TAG_PROTO_NONE] = &none_ops,
43
+DSA_TAG_DRIVER(none_ops);
44
+
45
+static void dsa_tag_driver_register(struct dsa_tag_driver *dsa_tag_driver,
46
+ struct module *owner)
47
+{
48
+ dsa_tag_driver->owner = owner;
49
+
50
+ mutex_lock(&dsa_tag_drivers_lock);
51
+ list_add_tail(&dsa_tag_driver->list, &dsa_tag_drivers_list);
52
+ mutex_unlock(&dsa_tag_drivers_lock);
53
+}
54
+
55
+void dsa_tag_drivers_register(struct dsa_tag_driver *dsa_tag_driver_array[],
56
+ unsigned int count, struct module *owner)
57
+{
58
+ unsigned int i;
59
+
60
+ for (i = 0; i < count; i++)
61
+ dsa_tag_driver_register(dsa_tag_driver_array[i], owner);
62
+}
63
+
64
+static void dsa_tag_driver_unregister(struct dsa_tag_driver *dsa_tag_driver)
65
+{
66
+ mutex_lock(&dsa_tag_drivers_lock);
67
+ list_del(&dsa_tag_driver->list);
68
+ mutex_unlock(&dsa_tag_drivers_lock);
69
+}
70
+EXPORT_SYMBOL_GPL(dsa_tag_drivers_register);
71
+
72
+void dsa_tag_drivers_unregister(struct dsa_tag_driver *dsa_tag_driver_array[],
73
+ unsigned int count)
74
+{
75
+ unsigned int i;
76
+
77
+ for (i = 0; i < count; i++)
78
+ dsa_tag_driver_unregister(dsa_tag_driver_array[i]);
79
+}
80
+EXPORT_SYMBOL_GPL(dsa_tag_drivers_unregister);
81
+
82
+const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops)
83
+{
84
+ return ops->name;
7185 };
7286
73
-const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol)
87
+const struct dsa_device_ops *dsa_tag_driver_get(int tag_protocol)
7488 {
89
+ struct dsa_tag_driver *dsa_tag_driver;
7590 const struct dsa_device_ops *ops;
91
+ bool found = false;
7692
77
- if (tag_protocol >= DSA_TAG_LAST)
78
- return ERR_PTR(-EINVAL);
79
- ops = dsa_device_ops[tag_protocol];
93
+ request_module("%s%d", DSA_TAG_DRIVER_ALIAS, tag_protocol);
8094
81
- if (!ops)
82
- return ERR_PTR(-ENOPROTOOPT);
95
+ mutex_lock(&dsa_tag_drivers_lock);
96
+ list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) {
97
+ ops = dsa_tag_driver->ops;
98
+ if (ops->proto == tag_protocol) {
99
+ found = true;
100
+ break;
101
+ }
102
+ }
103
+
104
+ if (found) {
105
+ if (!try_module_get(dsa_tag_driver->owner))
106
+ ops = ERR_PTR(-ENOPROTOOPT);
107
+ } else {
108
+ ops = ERR_PTR(-ENOPROTOOPT);
109
+ }
110
+
111
+ mutex_unlock(&dsa_tag_drivers_lock);
83112
84113 return ops;
114
+}
115
+
116
+void dsa_tag_driver_put(const struct dsa_device_ops *ops)
117
+{
118
+ struct dsa_tag_driver *dsa_tag_driver;
119
+
120
+ mutex_lock(&dsa_tag_drivers_lock);
121
+ list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) {
122
+ if (dsa_tag_driver->ops == ops) {
123
+ module_put(dsa_tag_driver->owner);
124
+ break;
125
+ }
126
+ }
127
+ mutex_unlock(&dsa_tag_drivers_lock);
85128 }
86129
87130 static int dev_is_class(struct device *dev, void *class)
....@@ -182,6 +225,15 @@
182225 skb->pkt_type = PACKET_HOST;
183226 skb->protocol = eth_type_trans(skb, skb->dev);
184227
228
+ if (unlikely(cpu_dp->ds->untag_bridge_pvid)) {
229
+ nskb = dsa_untag_bridge_pvid(skb);
230
+ if (!nskb) {
231
+ kfree_skb(skb);
232
+ return 0;
233
+ }
234
+ skb = nskb;
235
+ }
236
+
185237 s = this_cpu_ptr(p->stats64);
186238 u64_stats_update_begin(&s->syncp);
187239 s->rx_packets++;
....@@ -199,7 +251,9 @@
199251 #ifdef CONFIG_PM_SLEEP
200252 static bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
201253 {
202
- return dsa_is_user_port(ds, p) && ds->ports[p].slave;
254
+ const struct dsa_port *dp = dsa_to_port(ds, p);
255
+
256
+ return dp->type == DSA_PORT_TYPE_USER && dp->slave;
203257 }
204258
205259 int dsa_switch_suspend(struct dsa_switch *ds)
....@@ -211,7 +265,7 @@
211265 if (!dsa_is_port_initialized(ds, i))
212266 continue;
213267
214
- ret = dsa_slave_suspend(ds->ports[i].slave);
268
+ ret = dsa_slave_suspend(dsa_to_port(ds, i)->slave);
215269 if (ret)
216270 return ret;
217271 }
....@@ -238,7 +292,7 @@
238292 if (!dsa_is_port_initialized(ds, i))
239293 continue;
240294
241
- ret = dsa_slave_resume(ds->ports[i].slave);
295
+ ret = dsa_slave_resume(dsa_to_port(ds, i)->slave);
242296 if (ret)
243297 return ret;
244298 }
....@@ -282,6 +336,122 @@
282336 }
283337 EXPORT_SYMBOL_GPL(call_dsa_notifiers);
284338
339
+int dsa_devlink_param_get(struct devlink *dl, u32 id,
340
+ struct devlink_param_gset_ctx *ctx)
341
+{
342
+ struct dsa_switch *ds = dsa_devlink_to_ds(dl);
343
+
344
+ if (!ds->ops->devlink_param_get)
345
+ return -EOPNOTSUPP;
346
+
347
+ return ds->ops->devlink_param_get(ds, id, ctx);
348
+}
349
+EXPORT_SYMBOL_GPL(dsa_devlink_param_get);
350
+
351
+int dsa_devlink_param_set(struct devlink *dl, u32 id,
352
+ struct devlink_param_gset_ctx *ctx)
353
+{
354
+ struct dsa_switch *ds = dsa_devlink_to_ds(dl);
355
+
356
+ if (!ds->ops->devlink_param_set)
357
+ return -EOPNOTSUPP;
358
+
359
+ return ds->ops->devlink_param_set(ds, id, ctx);
360
+}
361
+EXPORT_SYMBOL_GPL(dsa_devlink_param_set);
362
+
363
+int dsa_devlink_params_register(struct dsa_switch *ds,
364
+ const struct devlink_param *params,
365
+ size_t params_count)
366
+{
367
+ return devlink_params_register(ds->devlink, params, params_count);
368
+}
369
+EXPORT_SYMBOL_GPL(dsa_devlink_params_register);
370
+
371
+void dsa_devlink_params_unregister(struct dsa_switch *ds,
372
+ const struct devlink_param *params,
373
+ size_t params_count)
374
+{
375
+ devlink_params_unregister(ds->devlink, params, params_count);
376
+}
377
+EXPORT_SYMBOL_GPL(dsa_devlink_params_unregister);
378
+
379
+int dsa_devlink_resource_register(struct dsa_switch *ds,
380
+ const char *resource_name,
381
+ u64 resource_size,
382
+ u64 resource_id,
383
+ u64 parent_resource_id,
384
+ const struct devlink_resource_size_params *size_params)
385
+{
386
+ return devlink_resource_register(ds->devlink, resource_name,
387
+ resource_size, resource_id,
388
+ parent_resource_id,
389
+ size_params);
390
+}
391
+EXPORT_SYMBOL_GPL(dsa_devlink_resource_register);
392
+
393
+void dsa_devlink_resources_unregister(struct dsa_switch *ds)
394
+{
395
+ devlink_resources_unregister(ds->devlink, NULL);
396
+}
397
+EXPORT_SYMBOL_GPL(dsa_devlink_resources_unregister);
398
+
399
+void dsa_devlink_resource_occ_get_register(struct dsa_switch *ds,
400
+ u64 resource_id,
401
+ devlink_resource_occ_get_t *occ_get,
402
+ void *occ_get_priv)
403
+{
404
+ return devlink_resource_occ_get_register(ds->devlink, resource_id,
405
+ occ_get, occ_get_priv);
406
+}
407
+EXPORT_SYMBOL_GPL(dsa_devlink_resource_occ_get_register);
408
+
409
+void dsa_devlink_resource_occ_get_unregister(struct dsa_switch *ds,
410
+ u64 resource_id)
411
+{
412
+ devlink_resource_occ_get_unregister(ds->devlink, resource_id);
413
+}
414
+EXPORT_SYMBOL_GPL(dsa_devlink_resource_occ_get_unregister);
415
+
416
+struct devlink_region *
417
+dsa_devlink_region_create(struct dsa_switch *ds,
418
+ const struct devlink_region_ops *ops,
419
+ u32 region_max_snapshots, u64 region_size)
420
+{
421
+ return devlink_region_create(ds->devlink, ops, region_max_snapshots,
422
+ region_size);
423
+}
424
+EXPORT_SYMBOL_GPL(dsa_devlink_region_create);
425
+
426
+struct devlink_region *
427
+dsa_devlink_port_region_create(struct dsa_switch *ds,
428
+ int port,
429
+ const struct devlink_port_region_ops *ops,
430
+ u32 region_max_snapshots, u64 region_size)
431
+{
432
+ struct dsa_port *dp = dsa_to_port(ds, port);
433
+
434
+ return devlink_port_region_create(&dp->devlink_port, ops,
435
+ region_max_snapshots,
436
+ region_size);
437
+}
438
+EXPORT_SYMBOL_GPL(dsa_devlink_port_region_create);
439
+
440
+void dsa_devlink_region_destroy(struct devlink_region *region)
441
+{
442
+ devlink_region_destroy(region);
443
+}
444
+EXPORT_SYMBOL_GPL(dsa_devlink_region_destroy);
445
+
446
+struct dsa_port *dsa_port_from_netdev(struct net_device *netdev)
447
+{
448
+ if (!netdev || !dsa_slave_dev_check(netdev))
449
+ return ERR_PTR(-ENODEV);
450
+
451
+ return dsa_slave_to_port(netdev);
452
+}
453
+EXPORT_SYMBOL_GPL(dsa_port_from_netdev);
454
+
285455 static int __init dsa_init_module(void)
286456 {
287457 int rc;
....@@ -295,16 +465,13 @@
295465 if (rc)
296466 goto register_notifier_fail;
297467
298
- rc = dsa_legacy_register();
299
- if (rc)
300
- goto legacy_register_fail;
301
-
302468 dev_add_pack(&dsa_pack_type);
469
+
470
+ dsa_tag_driver_register(&DSA_TAG_DRIVER_NAME(none_ops),
471
+ THIS_MODULE);
303472
304473 return 0;
305474
306
-legacy_register_fail:
307
- dsa_slave_unregister_notifier();
308475 register_notifier_fail:
309476 destroy_workqueue(dsa_owq);
310477
....@@ -314,9 +481,10 @@
314481
315482 static void __exit dsa_cleanup_module(void)
316483 {
484
+ dsa_tag_driver_unregister(&DSA_TAG_DRIVER_NAME(none_ops));
485
+
317486 dsa_slave_unregister_notifier();
318487 dev_remove_pack(&dsa_pack_type);
319
- dsa_legacy_unregister();
320488 destroy_workqueue(dsa_owq);
321489 }
322490 module_exit(dsa_cleanup_module);