treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / drivers / net / dsa / dsa_loop.c
blobfdcb70b9f0e4d908af502a14924ace21c26279b8
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Distributed Switch Architecture loopback driver
5 * Copyright (C) 2016, Florian Fainelli <f.fainelli@gmail.com>
6 */
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>
19 #include "dsa_loop.h"
21 struct dsa_loop_vlan {
22 u16 members;
23 u16 untagged;
26 struct dsa_loop_mib_entry {
27 char name[ETH_GSTRING_LEN];
28 unsigned long val;
31 enum 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,
39 static 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", },
46 struct dsa_loop_port {
47 struct dsa_loop_mib_entry mib[__DSA_LOOP_CNT_MAX];
50 #define DSA_LOOP_VLANS 5
52 struct 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;
61 static struct phy_device *phydevs[PHY_MAX_ADDR];
63 static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds,
64 int port,
65 enum dsa_tag_protocol mp)
67 dev_dbg(ds->dev, "%s: port: %d\n", __func__, port);
69 return DSA_TAG_PROTO_NONE;
72 static int dsa_loop_setup(struct dsa_switch *ds)
74 struct dsa_loop_priv *ps = ds->priv;
75 unsigned int i;
77 for (i = 0; i < ds->num_ports; i++)
78 memcpy(ps->ports[i].mib, dsa_loop_mibs,
79 sizeof(dsa_loop_mibs));
81 dev_dbg(ds->dev, "%s\n", __func__);
83 return 0;
86 static int dsa_loop_get_sset_count(struct dsa_switch *ds, int port, int sset)
88 if (sset != ETH_SS_STATS && sset != ETH_SS_PHY_STATS)
89 return 0;
91 return __DSA_LOOP_CNT_MAX;
94 static void dsa_loop_get_strings(struct dsa_switch *ds, int port,
95 u32 stringset, uint8_t *data)
97 struct dsa_loop_priv *ps = ds->priv;
98 unsigned int i;
100 if (stringset != ETH_SS_STATS && stringset != ETH_SS_PHY_STATS)
101 return;
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);
108 static void dsa_loop_get_ethtool_stats(struct dsa_switch *ds, int port,
109 uint64_t *data)
111 struct dsa_loop_priv *ps = ds->priv;
112 unsigned int i;
114 for (i = 0; i < __DSA_LOOP_CNT_MAX; i++)
115 data[i] = ps->ports[port].mib[i].val;
118 static int dsa_loop_phy_read(struct dsa_switch *ds, int port, int regnum)
120 struct dsa_loop_priv *ps = ds->priv;
121 struct mii_bus *bus = ps->bus;
122 int ret;
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++;
130 return ret;
133 static int dsa_loop_phy_write(struct dsa_switch *ds, int port,
134 int regnum, u16 value)
136 struct dsa_loop_priv *ps = ds->priv;
137 struct mii_bus *bus = ps->bus;
138 int ret;
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++;
146 return ret;
149 static int dsa_loop_port_bridge_join(struct dsa_switch *ds, int port,
150 struct net_device *bridge)
152 dev_dbg(ds->dev, "%s: port: %d, bridge: %s\n",
153 __func__, port, bridge->name);
155 return 0;
158 static void dsa_loop_port_bridge_leave(struct dsa_switch *ds, int port,
159 struct net_device *bridge)
161 dev_dbg(ds->dev, "%s: port: %d, bridge: %s\n",
162 __func__, port, bridge->name);
165 static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port,
166 u8 state)
168 dev_dbg(ds->dev, "%s: port: %d, state: %d\n",
169 __func__, port, state);
172 static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
173 bool vlan_filtering)
175 dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n",
176 __func__, port, vlan_filtering);
178 return 0;
181 static int
182 dsa_loop_port_vlan_prepare(struct dsa_switch *ds, int port,
183 const struct switchdev_obj_port_vlan *vlan)
185 struct dsa_loop_priv *ps = ds->priv;
186 struct mii_bus *bus = ps->bus;
188 dev_dbg(ds->dev, "%s: port: %d, vlan: %d-%d",
189 __func__, port, vlan->vid_begin, vlan->vid_end);
191 /* Just do a sleeping operation to make lockdep checks effective */
192 mdiobus_read(bus, ps->port_base + port, MII_BMSR);
194 if (vlan->vid_end > DSA_LOOP_VLANS)
195 return -ERANGE;
197 return 0;
200 static void dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,
201 const struct switchdev_obj_port_vlan *vlan)
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;
210 /* Just do a sleeping operation to make lockdep checks effective */
211 mdiobus_read(bus, ps->port_base + port, MII_BMSR);
213 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
214 vl = &ps->vlans[vid];
216 vl->members |= BIT(port);
217 if (untagged)
218 vl->untagged |= BIT(port);
219 else
220 vl->untagged &= ~BIT(port);
222 dev_dbg(ds->dev, "%s: port: %d vlan: %d, %stagged, pvid: %d\n",
223 __func__, port, vid, untagged ? "un" : "", pvid);
226 if (pvid)
227 ps->pvid = vid;
230 static int dsa_loop_port_vlan_del(struct dsa_switch *ds, int port,
231 const struct switchdev_obj_port_vlan *vlan)
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;
239 /* Just do a sleeping operation to make lockdep checks effective */
240 mdiobus_read(bus, ps->port_base + port, MII_BMSR);
242 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
243 vl = &ps->vlans[vid];
245 vl->members &= ~BIT(port);
246 if (untagged)
247 vl->untagged &= ~BIT(port);
249 if (pvid == vid)
250 pvid = 1;
252 dev_dbg(ds->dev, "%s: port: %d vlan: %d, %stagged, pvid: %d\n",
253 __func__, port, vid, untagged ? "un" : "", pvid);
255 ps->pvid = pvid;
257 return 0;
260 static 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,
278 static int dsa_loop_drv_probe(struct mdio_device *mdiodev)
280 struct dsa_loop_pdata *pdata = mdiodev->dev.platform_data;
281 struct dsa_loop_priv *ps;
282 struct dsa_switch *ds;
284 if (!pdata)
285 return -ENODEV;
287 dev_info(&mdiodev->dev, "%s: 0x%0x\n",
288 pdata->name, pdata->enabled_ports);
290 ds = devm_kzalloc(&mdiodev->dev, sizeof(*ds), GFP_KERNEL);
291 if (!ds)
292 return -ENOMEM;
294 ds->dev = &mdiodev->dev;
295 ds->num_ports = DSA_MAX_PORTS;
297 ps = devm_kzalloc(&mdiodev->dev, sizeof(*ps), GFP_KERNEL);
298 if (!ps)
299 return -ENOMEM;
301 ps->netdev = dev_get_by_name(&init_net, pdata->netdev);
302 if (!ps->netdev)
303 return -EPROBE_DEFER;
305 pdata->cd.netdev[DSA_LOOP_CPU_PORT] = &ps->netdev->dev;
307 ds->dev = &mdiodev->dev;
308 ds->ops = &dsa_loop_driver;
309 ds->priv = ps;
310 ps->bus = mdiodev->bus;
312 dev_set_drvdata(&mdiodev->dev, ds);
314 return dsa_register_switch(ds);
317 static void dsa_loop_drv_remove(struct mdio_device *mdiodev)
319 struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
320 struct dsa_loop_priv *ps = ds->priv;
322 dsa_unregister_switch(ds);
323 dev_put(ps->netdev);
326 static struct mdio_driver dsa_loop_drv = {
327 .mdiodrv.driver = {
328 .name = "dsa-loop",
330 .probe = dsa_loop_drv_probe,
331 .remove = dsa_loop_drv_remove,
334 #define NUM_FIXED_PHYS (DSA_LOOP_NUM_PORTS - 2)
336 static int __init dsa_loop_init(void)
338 struct fixed_phy_status status = {
339 .link = 1,
340 .speed = SPEED_100,
341 .duplex = DUPLEX_FULL,
343 unsigned int i;
345 for (i = 0; i < NUM_FIXED_PHYS; i++)
346 phydevs[i] = fixed_phy_register(PHY_POLL, &status, NULL);
348 return mdio_driver_register(&dsa_loop_drv);
350 module_init(dsa_loop_init);
352 static void __exit dsa_loop_exit(void)
354 unsigned int i;
356 mdio_driver_unregister(&dsa_loop_drv);
357 for (i = 0; i < NUM_FIXED_PHYS; i++)
358 if (!IS_ERR(phydevs[i]))
359 fixed_phy_unregister(phydevs[i]);
361 module_exit(dsa_loop_exit);
363 MODULE_LICENSE("GPL");
364 MODULE_AUTHOR("Florian Fainelli");
365 MODULE_DESCRIPTION("DSA loopback driver");