Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Handling of a conduit device, switching frames via its switch fabric CPU port
4 *
5 * Copyright (c) 2017 Savoir-faire Linux Inc.
6 * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
7 */
8
9#include <linux/ethtool.h>
10#include <linux/netdevice.h>
11#include <linux/netlink.h>
12#include <net/dsa.h>
13#include <net/netdev_lock.h>
14
15#include "conduit.h"
16#include "dsa.h"
17#include "port.h"
18#include "tag.h"
19
20static int dsa_conduit_get_regs_len(struct net_device *dev)
21{
22 struct dsa_port *cpu_dp = dev->dsa_ptr;
23 const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
24 struct dsa_switch *ds = cpu_dp->ds;
25 int port = cpu_dp->index;
26 int ret = 0;
27 int len;
28
29 if (ops && ops->get_regs_len) {
30 netdev_lock_ops(dev);
31 len = ops->get_regs_len(dev);
32 netdev_unlock_ops(dev);
33 if (len < 0)
34 return len;
35 ret += len;
36 }
37
38 ret += sizeof(struct ethtool_drvinfo);
39 ret += sizeof(struct ethtool_regs);
40
41 if (ds->ops->get_regs_len) {
42 len = ds->ops->get_regs_len(ds, port);
43 if (len < 0)
44 return len;
45 ret += len;
46 }
47
48 return ret;
49}
50
51static void dsa_conduit_get_regs(struct net_device *dev,
52 struct ethtool_regs *regs, void *data)
53{
54 struct dsa_port *cpu_dp = dev->dsa_ptr;
55 const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
56 struct dsa_switch *ds = cpu_dp->ds;
57 struct ethtool_drvinfo *cpu_info;
58 struct ethtool_regs *cpu_regs;
59 int port = cpu_dp->index;
60 int len;
61
62 if (ops && ops->get_regs_len && ops->get_regs) {
63 netdev_lock_ops(dev);
64 len = ops->get_regs_len(dev);
65 if (len < 0) {
66 netdev_unlock_ops(dev);
67 return;
68 }
69 regs->len = len;
70 ops->get_regs(dev, regs, data);
71 netdev_unlock_ops(dev);
72 data += regs->len;
73 }
74
75 cpu_info = (struct ethtool_drvinfo *)data;
76 strscpy(cpu_info->driver, "dsa", sizeof(cpu_info->driver));
77 data += sizeof(*cpu_info);
78 cpu_regs = (struct ethtool_regs *)data;
79 data += sizeof(*cpu_regs);
80
81 if (ds->ops->get_regs_len && ds->ops->get_regs) {
82 len = ds->ops->get_regs_len(ds, port);
83 if (len < 0)
84 return;
85 cpu_regs->len = len;
86 ds->ops->get_regs(ds, port, cpu_regs, data);
87 }
88}
89
90static ssize_t dsa_conduit_append_port_stats(struct dsa_switch *ds, int port,
91 u64 *data, size_t start)
92{
93 int count;
94
95 if (!ds->ops->get_sset_count)
96 return 0;
97
98 count = ds->ops->get_sset_count(ds, port, ETH_SS_STATS);
99 if (count < 0)
100 return count;
101
102 if (ds->ops->get_ethtool_stats)
103 ds->ops->get_ethtool_stats(ds, port, data + start);
104
105 return count;
106}
107
108static void dsa_conduit_get_ethtool_stats(struct net_device *dev,
109 struct ethtool_stats *stats,
110 u64 *data)
111{
112 struct dsa_port *dp, *cpu_dp = dev->dsa_ptr;
113 const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
114 struct dsa_switch_tree *dst = cpu_dp->dst;
115 int count, mcount = 0;
116
117 if (ops && ops->get_sset_count && ops->get_ethtool_stats) {
118 netdev_lock_ops(dev);
119 mcount = ops->get_sset_count(dev, ETH_SS_STATS);
120 ops->get_ethtool_stats(dev, stats, data);
121 netdev_unlock_ops(dev);
122 }
123
124 list_for_each_entry(dp, &dst->ports, list) {
125 if (!dsa_port_is_dsa(dp) && !dsa_port_is_cpu(dp))
126 continue;
127
128 count = dsa_conduit_append_port_stats(dp->ds, dp->index,
129 data, mcount);
130 if (count < 0)
131 return;
132
133 mcount += count;
134 }
135}
136
137static void dsa_conduit_get_ethtool_phy_stats(struct net_device *dev,
138 struct ethtool_stats *stats,
139 u64 *data)
140{
141 struct dsa_port *cpu_dp = dev->dsa_ptr;
142 const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
143 struct dsa_switch *ds = cpu_dp->ds;
144 int port = cpu_dp->index;
145 int count = 0;
146
147 if (dev->phydev && (!ops || !ops->get_ethtool_phy_stats)) {
148 count = phy_ethtool_get_sset_count(dev->phydev);
149 if (count >= 0)
150 phy_ethtool_get_stats(dev->phydev, stats, data);
151 } else if (ops && ops->get_sset_count && ops->get_ethtool_phy_stats) {
152 netdev_lock_ops(dev);
153 count = ops->get_sset_count(dev, ETH_SS_PHY_STATS);
154 ops->get_ethtool_phy_stats(dev, stats, data);
155 netdev_unlock_ops(dev);
156 }
157
158 if (count < 0)
159 count = 0;
160
161 if (ds->ops->get_ethtool_phy_stats)
162 ds->ops->get_ethtool_phy_stats(ds, port, data + count);
163}
164
165static void dsa_conduit_append_port_sset_count(struct dsa_switch *ds, int port,
166 int sset, int *count)
167{
168 if (ds->ops->get_sset_count)
169 *count += ds->ops->get_sset_count(ds, port, sset);
170}
171
172static int dsa_conduit_get_sset_count(struct net_device *dev, int sset)
173{
174 struct dsa_port *dp, *cpu_dp = dev->dsa_ptr;
175 const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
176 struct dsa_switch_tree *dst = cpu_dp->dst;
177 int count = 0;
178
179 netdev_lock_ops(dev);
180 if (sset == ETH_SS_PHY_STATS && dev->phydev &&
181 (!ops || !ops->get_ethtool_phy_stats))
182 count = phy_ethtool_get_sset_count(dev->phydev);
183 else if (ops && ops->get_sset_count)
184 count = ops->get_sset_count(dev, sset);
185 netdev_unlock_ops(dev);
186
187 if (count < 0)
188 count = 0;
189
190 list_for_each_entry(dp, &dst->ports, list) {
191 if (!dsa_port_is_dsa(dp) && !dsa_port_is_cpu(dp))
192 continue;
193
194 dsa_conduit_append_port_sset_count(dp->ds, dp->index, sset,
195 &count);
196 }
197
198 return count;
199}
200
201static ssize_t dsa_conduit_append_port_strings(struct dsa_switch *ds, int port,
202 u32 stringset, u8 *data,
203 size_t start)
204{
205 int len = ETH_GSTRING_LEN;
206 u8 pfx[8], *ndata;
207 int count, i;
208
209 if (!ds->ops->get_strings)
210 return 0;
211
212 snprintf(pfx, sizeof(pfx), "s%.2d_p%.2d", ds->index, port);
213 /* We do not want to be NULL-terminated, since this is a prefix */
214 pfx[sizeof(pfx) - 1] = '_';
215 ndata = data + start * len;
216 /* This function copies ETH_GSTRINGS_LEN bytes, we will mangle
217 * the output after to prepend our CPU port prefix we
218 * constructed earlier
219 */
220 ds->ops->get_strings(ds, port, stringset, ndata);
221 count = ds->ops->get_sset_count(ds, port, stringset);
222 if (count < 0)
223 return count;
224
225 for (i = 0; i < count; i++) {
226 memmove(ndata + (i * len + sizeof(pfx)),
227 ndata + i * len, len - sizeof(pfx));
228 memcpy(ndata + i * len, pfx, sizeof(pfx));
229 }
230
231 return count;
232}
233
234static void dsa_conduit_get_strings(struct net_device *dev, u32 stringset,
235 u8 *data)
236{
237 struct dsa_port *dp, *cpu_dp = dev->dsa_ptr;
238 const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
239 struct dsa_switch_tree *dst = cpu_dp->dst;
240 int count, mcount = 0;
241
242 netdev_lock_ops(dev);
243 if (stringset == ETH_SS_PHY_STATS && dev->phydev &&
244 !ops->get_ethtool_phy_stats) {
245 mcount = phy_ethtool_get_sset_count(dev->phydev);
246 if (mcount < 0)
247 mcount = 0;
248 else
249 phy_ethtool_get_strings(dev->phydev, data);
250 } else if (ops->get_sset_count && ops->get_strings) {
251 mcount = ops->get_sset_count(dev, stringset);
252 if (mcount < 0)
253 mcount = 0;
254 ops->get_strings(dev, stringset, data);
255 }
256 netdev_unlock_ops(dev);
257
258 list_for_each_entry(dp, &dst->ports, list) {
259 if (!dsa_port_is_dsa(dp) && !dsa_port_is_cpu(dp))
260 continue;
261
262 count = dsa_conduit_append_port_strings(dp->ds, dp->index,
263 stringset, data,
264 mcount);
265 if (count < 0)
266 return;
267
268 mcount += count;
269 }
270}
271
272/* Deny PTP operations on conduit if there is at least one switch in the tree
273 * that is PTP capable.
274 */
275int __dsa_conduit_hwtstamp_validate(struct net_device *dev,
276 const struct kernel_hwtstamp_config *config,
277 struct netlink_ext_ack *extack)
278{
279 struct dsa_port *cpu_dp = dev->dsa_ptr;
280 struct dsa_switch *ds = cpu_dp->ds;
281 struct dsa_switch_tree *dst;
282 struct dsa_port *dp;
283
284 dst = ds->dst;
285
286 list_for_each_entry(dp, &dst->ports, list) {
287 if (dsa_port_supports_hwtstamp(dp)) {
288 NL_SET_ERR_MSG(extack,
289 "HW timestamping not allowed on DSA conduit when switch supports the operation");
290 return -EBUSY;
291 }
292 }
293
294 return 0;
295}
296
297static int dsa_conduit_ethtool_setup(struct net_device *dev)
298{
299 struct dsa_port *cpu_dp = dev->dsa_ptr;
300 struct dsa_switch *ds = cpu_dp->ds;
301 struct ethtool_ops *ops;
302
303 if (netif_is_lag_master(dev))
304 return 0;
305
306 ops = devm_kzalloc(ds->dev, sizeof(*ops), GFP_KERNEL);
307 if (!ops)
308 return -ENOMEM;
309
310 cpu_dp->orig_ethtool_ops = dev->ethtool_ops;
311 if (cpu_dp->orig_ethtool_ops)
312 memcpy(ops, cpu_dp->orig_ethtool_ops, sizeof(*ops));
313
314 ops->get_regs_len = dsa_conduit_get_regs_len;
315 ops->get_regs = dsa_conduit_get_regs;
316 ops->get_sset_count = dsa_conduit_get_sset_count;
317 ops->get_ethtool_stats = dsa_conduit_get_ethtool_stats;
318 ops->get_strings = dsa_conduit_get_strings;
319 ops->get_ethtool_phy_stats = dsa_conduit_get_ethtool_phy_stats;
320
321 dev->ethtool_ops = ops;
322
323 return 0;
324}
325
326static void dsa_conduit_ethtool_teardown(struct net_device *dev)
327{
328 struct dsa_port *cpu_dp = dev->dsa_ptr;
329
330 if (netif_is_lag_master(dev))
331 return;
332
333 dev->ethtool_ops = cpu_dp->orig_ethtool_ops;
334 cpu_dp->orig_ethtool_ops = NULL;
335}
336
337/* Keep the conduit always promiscuous if the tagging protocol requires that
338 * (garbles MAC DA) or if it doesn't support unicast filtering, case in which
339 * it would revert to promiscuous mode as soon as we call dev_uc_add() on it
340 * anyway.
341 */
342static void dsa_conduit_set_promiscuity(struct net_device *dev, int inc)
343{
344 const struct dsa_device_ops *ops = dev->dsa_ptr->tag_ops;
345
346 if ((dev->priv_flags & IFF_UNICAST_FLT) && !ops->promisc_on_conduit)
347 return;
348
349 ASSERT_RTNL();
350
351 dev_set_promiscuity(dev, inc);
352}
353
354static ssize_t tagging_show(struct device *d, struct device_attribute *attr,
355 char *buf)
356{
357 struct net_device *dev = to_net_dev(d);
358 struct dsa_port *cpu_dp = dev->dsa_ptr;
359
360 return sysfs_emit(buf, "%s\n",
361 dsa_tag_protocol_to_str(cpu_dp->tag_ops));
362}
363
364static ssize_t tagging_store(struct device *d, struct device_attribute *attr,
365 const char *buf, size_t count)
366{
367 const struct dsa_device_ops *new_tag_ops, *old_tag_ops;
368 const char *end = strchrnul(buf, '\n'), *name;
369 struct net_device *dev = to_net_dev(d);
370 struct dsa_port *cpu_dp = dev->dsa_ptr;
371 size_t len = end - buf;
372 int err;
373
374 /* Empty string passed */
375 if (!len)
376 return -ENOPROTOOPT;
377
378 name = kstrndup(buf, len, GFP_KERNEL);
379 if (!name)
380 return -ENOMEM;
381
382 old_tag_ops = cpu_dp->tag_ops;
383 new_tag_ops = dsa_tag_driver_get_by_name(name);
384 kfree(name);
385 /* Bad tagger name? */
386 if (IS_ERR(new_tag_ops))
387 return PTR_ERR(new_tag_ops);
388
389 if (new_tag_ops == old_tag_ops)
390 /* Drop the temporarily held duplicate reference, since
391 * the DSA switch tree uses this tagger.
392 */
393 goto out;
394
395 err = dsa_tree_change_tag_proto(cpu_dp->ds->dst, new_tag_ops,
396 old_tag_ops);
397 if (err) {
398 /* On failure the old tagger is restored, so we don't need the
399 * driver for the new one.
400 */
401 dsa_tag_driver_put(new_tag_ops);
402 return err;
403 }
404
405 /* On success we no longer need the module for the old tagging protocol
406 */
407out:
408 dsa_tag_driver_put(old_tag_ops);
409 return count;
410}
411static DEVICE_ATTR_RW(tagging);
412
413static struct attribute *dsa_user_attrs[] = {
414 &dev_attr_tagging.attr,
415 NULL
416};
417
418static const struct attribute_group dsa_group = {
419 .name = "dsa",
420 .attrs = dsa_user_attrs,
421};
422
423static void dsa_conduit_reset_mtu(struct net_device *dev)
424{
425 int err;
426
427 err = dev_set_mtu(dev, ETH_DATA_LEN);
428 if (err)
429 netdev_dbg(dev,
430 "Unable to reset MTU to exclude DSA overheads\n");
431}
432
433int dsa_conduit_setup(struct net_device *dev, struct dsa_port *cpu_dp)
434{
435 const struct dsa_device_ops *tag_ops = cpu_dp->tag_ops;
436 struct dsa_switch *ds = cpu_dp->ds;
437 struct device_link *consumer_link;
438 int mtu, ret;
439
440 mtu = ETH_DATA_LEN + dsa_tag_protocol_overhead(tag_ops);
441
442 /* The DSA conduit must use SET_NETDEV_DEV for this to work. */
443 if (!netif_is_lag_master(dev)) {
444 consumer_link = device_link_add(ds->dev, dev->dev.parent,
445 DL_FLAG_AUTOREMOVE_CONSUMER);
446 if (!consumer_link)
447 netdev_err(dev,
448 "Failed to create a device link to DSA switch %s\n",
449 dev_name(ds->dev));
450 }
451
452 /* The switch driver may not implement ->port_change_mtu(), case in
453 * which dsa_user_change_mtu() will not update the conduit MTU either,
454 * so we need to do that here.
455 */
456 ret = dev_set_mtu(dev, mtu);
457 if (ret)
458 netdev_warn(dev, "error %d setting MTU to %d to include DSA overhead\n",
459 ret, mtu);
460
461 /* If we use a tagging format that doesn't have an ethertype
462 * field, make sure that all packets from this point on get
463 * sent to the tag format's receive function.
464 */
465 wmb();
466
467 dev->dsa_ptr = cpu_dp;
468
469 dsa_conduit_set_promiscuity(dev, 1);
470
471 ret = dsa_conduit_ethtool_setup(dev);
472 if (ret)
473 goto out_err_reset_promisc;
474
475 ret = sysfs_create_group(&dev->dev.kobj, &dsa_group);
476 if (ret)
477 goto out_err_ethtool_teardown;
478
479 return ret;
480
481out_err_ethtool_teardown:
482 dsa_conduit_ethtool_teardown(dev);
483out_err_reset_promisc:
484 dsa_conduit_set_promiscuity(dev, -1);
485 return ret;
486}
487
488void dsa_conduit_teardown(struct net_device *dev)
489{
490 sysfs_remove_group(&dev->dev.kobj, &dsa_group);
491 dsa_conduit_ethtool_teardown(dev);
492 dsa_conduit_reset_mtu(dev);
493 dsa_conduit_set_promiscuity(dev, -1);
494
495 dev->dsa_ptr = NULL;
496
497 /* If we used a tagging format that doesn't have an ethertype
498 * field, make sure that all packets from this point get sent
499 * without the tag and go through the regular receive path.
500 */
501 wmb();
502}
503
504int dsa_conduit_lag_setup(struct net_device *lag_dev, struct dsa_port *cpu_dp,
505 struct netdev_lag_upper_info *uinfo,
506 struct netlink_ext_ack *extack)
507{
508 bool conduit_setup = false;
509 int err;
510
511 if (!netdev_uses_dsa(lag_dev)) {
512 err = dsa_conduit_setup(lag_dev, cpu_dp);
513 if (err)
514 return err;
515
516 conduit_setup = true;
517 }
518
519 err = dsa_port_lag_join(cpu_dp, lag_dev, uinfo, extack);
520 if (err) {
521 NL_SET_ERR_MSG_WEAK_MOD(extack, "CPU port failed to join LAG");
522 goto out_conduit_teardown;
523 }
524
525 return 0;
526
527out_conduit_teardown:
528 if (conduit_setup)
529 dsa_conduit_teardown(lag_dev);
530 return err;
531}
532
533/* Tear down a conduit if there isn't any other user port on it,
534 * optionally also destroying LAG information.
535 */
536void dsa_conduit_lag_teardown(struct net_device *lag_dev,
537 struct dsa_port *cpu_dp)
538{
539 struct net_device *upper;
540 struct list_head *iter;
541
542 dsa_port_lag_leave(cpu_dp, lag_dev);
543
544 netdev_for_each_upper_dev_rcu(lag_dev, upper, iter)
545 if (dsa_user_dev_check(upper))
546 return;
547
548 dsa_conduit_teardown(lag_dev);
549}