blob: cd8d89b50f8e59484b2f2aba83be764d5f27c546 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Distributed Switch Architecture loopback driver
4 *
5 * Copyright (C) 2016, Florian Fainelli <f.fainelli@gmail.com>
6 */
7
8#include <linux/platform_device.h>
9#include <linux/netdevice.h>
10#include <linux/phy.h>
11#include <linux/phy_fixed.h>
12#include <linux/export.h>
13#include <linux/ethtool.h>
14#include <linux/workqueue.h>
15#include <linux/module.h>
16#include <linux/if_bridge.h>
17#include <net/dsa.h>
18
19#include "dsa_loop.h"
20
21struct dsa_loop_vlan {
22 u16 members;
23 u16 untagged;
24};
25
26struct dsa_loop_mib_entry {
27 char name[ETH_GSTRING_LEN];
28 unsigned long val;
29};
30
31enum dsa_loop_mib_counters {
32 DSA_LOOP_PHY_READ_OK,
33 DSA_LOOP_PHY_READ_ERR,
34 DSA_LOOP_PHY_WRITE_OK,
35 DSA_LOOP_PHY_WRITE_ERR,
36 __DSA_LOOP_CNT_MAX,
37};
38
39static struct dsa_loop_mib_entry dsa_loop_mibs[] = {
40 [DSA_LOOP_PHY_READ_OK] = { "phy_read_ok", },
41 [DSA_LOOP_PHY_READ_ERR] = { "phy_read_err", },
42 [DSA_LOOP_PHY_WRITE_OK] = { "phy_write_ok", },
43 [DSA_LOOP_PHY_WRITE_ERR] = { "phy_write_err", },
44};
45
46struct dsa_loop_port {
47 struct dsa_loop_mib_entry mib[__DSA_LOOP_CNT_MAX];
48};
49
50#define DSA_LOOP_VLANS 5
51
52struct dsa_loop_priv {
53 struct mii_bus *bus;
54 unsigned int port_base;
55 struct dsa_loop_vlan vlans[DSA_LOOP_VLANS];
56 struct net_device *netdev;
57 struct dsa_loop_port ports[DSA_MAX_PORTS];
58 u16 pvid;
59};
60
61static struct phy_device *phydevs[PHY_MAX_ADDR];
62
63static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds,
64 int port,
65 enum dsa_tag_protocol mp)
66{
67 dev_dbg(ds->dev, "%s: port: %d\n", __func__, port);
68
69 return DSA_TAG_PROTO_NONE;
70}
71
72static int dsa_loop_setup(struct dsa_switch *ds)
73{
74 struct dsa_loop_priv *ps = ds->priv;
75 unsigned int i;
76
77 for (i = 0; i < ds->num_ports; i++)
78 memcpy(ps->ports[i].mib, dsa_loop_mibs,
79 sizeof(dsa_loop_mibs));
80
81 dev_dbg(ds->dev, "%s\n", __func__);
82
83 return 0;
84}
85
86static int dsa_loop_get_sset_count(struct dsa_switch *ds, int port, int sset)
87{
88 if (sset != ETH_SS_STATS && sset != ETH_SS_PHY_STATS)
89 return 0;
90
91 return __DSA_LOOP_CNT_MAX;
92}
93
94static void dsa_loop_get_strings(struct dsa_switch *ds, int port,
95 u32 stringset, uint8_t *data)
96{
97 struct dsa_loop_priv *ps = ds->priv;
98 unsigned int i;
99
100 if (stringset != ETH_SS_STATS && stringset != ETH_SS_PHY_STATS)
101 return;
102
103 for (i = 0; i < __DSA_LOOP_CNT_MAX; i++)
104 memcpy(data + i * ETH_GSTRING_LEN,
105 ps->ports[port].mib[i].name, ETH_GSTRING_LEN);
106}
107
108static void dsa_loop_get_ethtool_stats(struct dsa_switch *ds, int port,
109 uint64_t *data)
110{
111 struct dsa_loop_priv *ps = ds->priv;
112 unsigned int i;
113
114 for (i = 0; i < __DSA_LOOP_CNT_MAX; i++)
115 data[i] = ps->ports[port].mib[i].val;
116}
117
118static int dsa_loop_phy_read(struct dsa_switch *ds, int port, int regnum)
119{
120 struct dsa_loop_priv *ps = ds->priv;
121 struct mii_bus *bus = ps->bus;
122 int ret;
123
124 ret = mdiobus_read_nested(bus, ps->port_base + port, regnum);
125 if (ret < 0)
126 ps->ports[port].mib[DSA_LOOP_PHY_READ_ERR].val++;
127 else
128 ps->ports[port].mib[DSA_LOOP_PHY_READ_OK].val++;
129
130 return ret;
131}
132
133static int dsa_loop_phy_write(struct dsa_switch *ds, int port,
134 int regnum, u16 value)
135{
136 struct dsa_loop_priv *ps = ds->priv;
137 struct mii_bus *bus = ps->bus;
138 int ret;
139
140 ret = mdiobus_write_nested(bus, ps->port_base + port, regnum, value);
141 if (ret < 0)
142 ps->ports[port].mib[DSA_LOOP_PHY_WRITE_ERR].val++;
143 else
144 ps->ports[port].mib[DSA_LOOP_PHY_WRITE_OK].val++;
145
146 return ret;
147}
148
149static int dsa_loop_port_bridge_join(struct dsa_switch *ds, int port,
150 struct net_device *bridge)
151{
152 dev_dbg(ds->dev, "%s: port: %d, bridge: %s\n",
153 __func__, port, bridge->name);
154
155 return 0;
156}
157
158static void dsa_loop_port_bridge_leave(struct dsa_switch *ds, int port,
159 struct net_device *bridge)
160{
161 dev_dbg(ds->dev, "%s: port: %d, bridge: %s\n",
162 __func__, port, bridge->name);
163}
164
165static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port,
166 u8 state)
167{
168 dev_dbg(ds->dev, "%s: port: %d, state: %d\n",
169 __func__, port, state);
170}
171
172static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
173 bool vlan_filtering)
174{
175 dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n",
176 __func__, port, vlan_filtering);
177
178 return 0;
179}
180
181static int
182dsa_loop_port_vlan_prepare(struct dsa_switch *ds, int port,
183 const struct switchdev_obj_port_vlan *vlan)
184{
185 struct dsa_loop_priv *ps = ds->priv;
186 struct mii_bus *bus = ps->bus;
187
188 dev_dbg(ds->dev, "%s: port: %d, vlan: %d-%d",
189 __func__, port, vlan->vid_begin, vlan->vid_end);
190
191 /* Just do a sleeping operation to make lockdep checks effective */
192 mdiobus_read(bus, ps->port_base + port, MII_BMSR);
193
194 if (vlan->vid_end > DSA_LOOP_VLANS)
195 return -ERANGE;
196
197 return 0;
198}
199
200static void dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,
201 const struct switchdev_obj_port_vlan *vlan)
202{
203 bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
204 bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
205 struct dsa_loop_priv *ps = ds->priv;
206 struct mii_bus *bus = ps->bus;
207 struct dsa_loop_vlan *vl;
208 u16 vid;
209
210 /* Just do a sleeping operation to make lockdep checks effective */
211 mdiobus_read(bus, ps->port_base + port, MII_BMSR);
212
213 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
214 vl = &ps->vlans[vid];
215
216 vl->members |= BIT(port);
217 if (untagged)
218 vl->untagged |= BIT(port);
219 else
220 vl->untagged &= ~BIT(port);
221
222 dev_dbg(ds->dev, "%s: port: %d vlan: %d, %stagged, pvid: %d\n",
223 __func__, port, vid, untagged ? "un" : "", pvid);
224 }
225
226 if (pvid)
227 ps->pvid = vid;
228}
229
230static int dsa_loop_port_vlan_del(struct dsa_switch *ds, int port,
231 const struct switchdev_obj_port_vlan *vlan)
232{
233 bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
234 struct dsa_loop_priv *ps = ds->priv;
235 struct mii_bus *bus = ps->bus;
236 struct dsa_loop_vlan *vl;
237 u16 vid, pvid = ps->pvid;
238
239 /* Just do a sleeping operation to make lockdep checks effective */
240 mdiobus_read(bus, ps->port_base + port, MII_BMSR);
241
242 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
243 vl = &ps->vlans[vid];
244
245 vl->members &= ~BIT(port);
246 if (untagged)
247 vl->untagged &= ~BIT(port);
248
249 if (pvid == vid)
250 pvid = 1;
251
252 dev_dbg(ds->dev, "%s: port: %d vlan: %d, %stagged, pvid: %d\n",
253 __func__, port, vid, untagged ? "un" : "", pvid);
254 }
255 ps->pvid = pvid;
256
257 return 0;
258}
259
260static const struct dsa_switch_ops dsa_loop_driver = {
261 .get_tag_protocol = dsa_loop_get_protocol,
262 .setup = dsa_loop_setup,
263 .get_strings = dsa_loop_get_strings,
264 .get_ethtool_stats = dsa_loop_get_ethtool_stats,
265 .get_sset_count = dsa_loop_get_sset_count,
266 .get_ethtool_phy_stats = dsa_loop_get_ethtool_stats,
267 .phy_read = dsa_loop_phy_read,
268 .phy_write = dsa_loop_phy_write,
269 .port_bridge_join = dsa_loop_port_bridge_join,
270 .port_bridge_leave = dsa_loop_port_bridge_leave,
271 .port_stp_state_set = dsa_loop_port_stp_state_set,
272 .port_vlan_filtering = dsa_loop_port_vlan_filtering,
273 .port_vlan_prepare = dsa_loop_port_vlan_prepare,
274 .port_vlan_add = dsa_loop_port_vlan_add,
275 .port_vlan_del = dsa_loop_port_vlan_del,
276};
277
278static int dsa_loop_drv_probe(struct mdio_device *mdiodev)
279{
280 struct dsa_loop_pdata *pdata = mdiodev->dev.platform_data;
281 struct dsa_loop_priv *ps;
282 struct dsa_switch *ds;
283
284 if (!pdata)
285 return -ENODEV;
286
287 dev_info(&mdiodev->dev, "%s: 0x%0x\n",
288 pdata->name, pdata->enabled_ports);
289
290 ds = dsa_switch_alloc(&mdiodev->dev, DSA_MAX_PORTS);
291 if (!ds)
292 return -ENOMEM;
293
294 ps = devm_kzalloc(&mdiodev->dev, sizeof(*ps), GFP_KERNEL);
295 if (!ps)
296 return -ENOMEM;
297
298 ps->netdev = dev_get_by_name(&init_net, pdata->netdev);
299 if (!ps->netdev)
300 return -EPROBE_DEFER;
301
302 pdata->cd.netdev[DSA_LOOP_CPU_PORT] = &ps->netdev->dev;
303
304 ds->dev = &mdiodev->dev;
305 ds->ops = &dsa_loop_driver;
306 ds->priv = ps;
307 ps->bus = mdiodev->bus;
308
309 dev_set_drvdata(&mdiodev->dev, ds);
310
311 return dsa_register_switch(ds);
312}
313
314static void dsa_loop_drv_remove(struct mdio_device *mdiodev)
315{
316 struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
317 struct dsa_loop_priv *ps = ds->priv;
318
319 dsa_unregister_switch(ds);
320 dev_put(ps->netdev);
321}
322
323static struct mdio_driver dsa_loop_drv = {
324 .mdiodrv.driver = {
325 .name = "dsa-loop",
326 },
327 .probe = dsa_loop_drv_probe,
328 .remove = dsa_loop_drv_remove,
329};
330
331#define NUM_FIXED_PHYS (DSA_LOOP_NUM_PORTS - 2)
332
333static void dsa_loop_phydevs_unregister(void)
334{
335 unsigned int i;
336
337 for (i = 0; i < NUM_FIXED_PHYS; i++)
338 if (!IS_ERR(phydevs[i])) {
339 fixed_phy_unregister(phydevs[i]);
340 phy_device_free(phydevs[i]);
341 }
342}
343
344static int __init dsa_loop_init(void)
345{
346 struct fixed_phy_status status = {
347 .link = 1,
348 .speed = SPEED_100,
349 .duplex = DUPLEX_FULL,
350 };
351 unsigned int i, ret;
352
353 for (i = 0; i < NUM_FIXED_PHYS; i++)
354 phydevs[i] = fixed_phy_register(PHY_POLL, &status, NULL);
355
356 ret = mdio_driver_register(&dsa_loop_drv);
357 if (ret)
358 dsa_loop_phydevs_unregister();
359
360 return ret;
361}
362module_init(dsa_loop_init);
363
364static void __exit dsa_loop_exit(void)
365{
366 mdio_driver_unregister(&dsa_loop_drv);
367 dsa_loop_phydevs_unregister();
368}
369module_exit(dsa_loop_exit);
370
371MODULE_SOFTDEP("pre: dsa_loop_bdinfo");
372MODULE_LICENSE("GPL");
373MODULE_AUTHOR("Florian Fainelli");
374MODULE_DESCRIPTION("DSA loopback driver");