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