blob: 748cc6394bbb9094fc6bfaeaccb9b270e44dce2e [file] [log] [blame]
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001/*
2 * net/dsa/slave.c - Slave device handling
Lennert Buytenheke84665c2009-03-20 09:52:09 +00003 * Copyright (c) 2008-2009 Marvell Semiconductor
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 */
10
11#include <linux/list.h>
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -080012#include <linux/etherdevice.h>
Florian Fainellib73adef2015-02-24 13:15:33 -080013#include <linux/netdevice.h>
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000014#include <linux/phy.h>
Florian Fainellia2820542014-10-17 16:02:13 -070015#include <linux/phy_fixed.h>
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -070016#include <linux/of_net.h>
17#include <linux/of_mdio.h>
Florian Fainellib73adef2015-02-24 13:15:33 -080018#include <net/rtnetlink.h>
Scott Feldman98237d42015-03-15 21:07:15 -070019#include <net/switchdev.h>
Florian Fainellib73adef2015-02-24 13:15:33 -080020#include <linux/if_bridge.h>
Florian Fainelli04ff53f2015-07-31 11:42:57 -070021#include <linux/netpoll.h>
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000022#include "dsa_priv.h"
23
24/* slave mii_bus handling ***************************************************/
25static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg)
26{
27 struct dsa_switch *ds = bus->priv;
28
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -070029 if (ds->phys_mii_mask & (1 << addr))
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000030 return ds->drv->phy_read(ds, addr, reg);
31
32 return 0xffff;
33}
34
35static int dsa_slave_phy_write(struct mii_bus *bus, int addr, int reg, u16 val)
36{
37 struct dsa_switch *ds = bus->priv;
38
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -070039 if (ds->phys_mii_mask & (1 << addr))
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000040 return ds->drv->phy_write(ds, addr, reg, val);
41
42 return 0;
43}
44
45void dsa_slave_mii_bus_init(struct dsa_switch *ds)
46{
47 ds->slave_mii_bus->priv = (void *)ds;
48 ds->slave_mii_bus->name = "dsa slave smi";
49 ds->slave_mii_bus->read = dsa_slave_phy_read;
50 ds->slave_mii_bus->write = dsa_slave_phy_write;
Florian Fainellif490be02013-01-21 09:58:50 +000051 snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d:%.2x",
52 ds->index, ds->pd->sw_addr);
Alexander Duyckb4d23942014-09-15 13:00:27 -040053 ds->slave_mii_bus->parent = ds->master_dev;
Vivien Didelot24df8982015-01-20 19:13:32 -050054 ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000055}
56
57
58/* slave device handling ****************************************************/
Nicolas Dichtelabd2be02015-04-02 17:07:08 +020059static int dsa_slave_get_iflink(const struct net_device *dev)
Lennert Buytenhekc0840802009-03-20 09:49:49 +000060{
61 struct dsa_slave_priv *p = netdev_priv(dev);
Lennert Buytenhekc0840802009-03-20 09:49:49 +000062
Nicolas Dichtelabd2be02015-04-02 17:07:08 +020063 return p->parent->dst->master_netdev->ifindex;
Lennert Buytenhekc0840802009-03-20 09:49:49 +000064}
65
Florian Fainellib73adef2015-02-24 13:15:33 -080066static inline bool dsa_port_is_bridged(struct dsa_slave_priv *p)
67{
68 return !!p->bridge_dev;
69}
70
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000071static int dsa_slave_open(struct net_device *dev)
72{
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -080073 struct dsa_slave_priv *p = netdev_priv(dev);
Lennert Buytenheke84665c2009-03-20 09:52:09 +000074 struct net_device *master = p->parent->dst->master_netdev;
Florian Fainellib2f2af22014-09-24 17:05:18 -070075 struct dsa_switch *ds = p->parent;
Florian Fainellib73adef2015-02-24 13:15:33 -080076 u8 stp_state = dsa_port_is_bridged(p) ?
77 BR_STATE_BLOCKING : BR_STATE_FORWARDING;
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -080078 int err;
79
80 if (!(master->flags & IFF_UP))
81 return -ENETDOWN;
82
Joe Perches8feedbb2012-05-08 18:56:57 +000083 if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) {
Jiri Pirkoa748ee22010-04-01 21:22:09 +000084 err = dev_uc_add(master, dev->dev_addr);
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -080085 if (err < 0)
86 goto out;
87 }
88
89 if (dev->flags & IFF_ALLMULTI) {
90 err = dev_set_allmulti(master, 1);
91 if (err < 0)
92 goto del_unicast;
93 }
94 if (dev->flags & IFF_PROMISC) {
95 err = dev_set_promiscuity(master, 1);
96 if (err < 0)
97 goto clear_allmulti;
98 }
99
Florian Fainellib2f2af22014-09-24 17:05:18 -0700100 if (ds->drv->port_enable) {
101 err = ds->drv->port_enable(ds, p->port, p->phy);
102 if (err)
103 goto clear_promisc;
104 }
105
Florian Fainellib73adef2015-02-24 13:15:33 -0800106 if (ds->drv->port_stp_update)
107 ds->drv->port_stp_update(ds, p->port, stp_state);
108
Florian Fainellif7f1de52014-09-24 17:05:17 -0700109 if (p->phy)
110 phy_start(p->phy);
111
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000112 return 0;
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800113
Florian Fainellib2f2af22014-09-24 17:05:18 -0700114clear_promisc:
115 if (dev->flags & IFF_PROMISC)
Gilad Ben-Yossef4fdeddf2015-06-25 16:50:13 +0300116 dev_set_promiscuity(master, -1);
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800117clear_allmulti:
118 if (dev->flags & IFF_ALLMULTI)
119 dev_set_allmulti(master, -1);
120del_unicast:
Joe Perches8feedbb2012-05-08 18:56:57 +0000121 if (!ether_addr_equal(dev->dev_addr, master->dev_addr))
Jiri Pirkoa748ee22010-04-01 21:22:09 +0000122 dev_uc_del(master, dev->dev_addr);
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800123out:
124 return err;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000125}
126
127static int dsa_slave_close(struct net_device *dev)
128{
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800129 struct dsa_slave_priv *p = netdev_priv(dev);
Lennert Buytenheke84665c2009-03-20 09:52:09 +0000130 struct net_device *master = p->parent->dst->master_netdev;
Florian Fainellib2f2af22014-09-24 17:05:18 -0700131 struct dsa_switch *ds = p->parent;
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800132
Florian Fainellif7f1de52014-09-24 17:05:17 -0700133 if (p->phy)
134 phy_stop(p->phy);
135
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800136 dev_mc_unsync(master, dev);
Jiri Pirkoa748ee22010-04-01 21:22:09 +0000137 dev_uc_unsync(master, dev);
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800138 if (dev->flags & IFF_ALLMULTI)
139 dev_set_allmulti(master, -1);
140 if (dev->flags & IFF_PROMISC)
141 dev_set_promiscuity(master, -1);
142
Joe Perches8feedbb2012-05-08 18:56:57 +0000143 if (!ether_addr_equal(dev->dev_addr, master->dev_addr))
Jiri Pirkoa748ee22010-04-01 21:22:09 +0000144 dev_uc_del(master, dev->dev_addr);
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800145
Florian Fainellib2f2af22014-09-24 17:05:18 -0700146 if (ds->drv->port_disable)
147 ds->drv->port_disable(ds, p->port, p->phy);
148
Florian Fainellib73adef2015-02-24 13:15:33 -0800149 if (ds->drv->port_stp_update)
150 ds->drv->port_stp_update(ds, p->port, BR_STATE_DISABLED);
151
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000152 return 0;
153}
154
155static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
156{
157 struct dsa_slave_priv *p = netdev_priv(dev);
Lennert Buytenheke84665c2009-03-20 09:52:09 +0000158 struct net_device *master = p->parent->dst->master_netdev;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000159
160 if (change & IFF_ALLMULTI)
161 dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1);
162 if (change & IFF_PROMISC)
163 dev_set_promiscuity(master, dev->flags & IFF_PROMISC ? 1 : -1);
164}
165
166static void dsa_slave_set_rx_mode(struct net_device *dev)
167{
168 struct dsa_slave_priv *p = netdev_priv(dev);
Lennert Buytenheke84665c2009-03-20 09:52:09 +0000169 struct net_device *master = p->parent->dst->master_netdev;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000170
171 dev_mc_sync(master, dev);
Jiri Pirkoa748ee22010-04-01 21:22:09 +0000172 dev_uc_sync(master, dev);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000173}
174
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800175static int dsa_slave_set_mac_address(struct net_device *dev, void *a)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000176{
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800177 struct dsa_slave_priv *p = netdev_priv(dev);
Lennert Buytenheke84665c2009-03-20 09:52:09 +0000178 struct net_device *master = p->parent->dst->master_netdev;
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800179 struct sockaddr *addr = a;
180 int err;
181
182 if (!is_valid_ether_addr(addr->sa_data))
183 return -EADDRNOTAVAIL;
184
185 if (!(dev->flags & IFF_UP))
186 goto out;
187
Joe Perches8feedbb2012-05-08 18:56:57 +0000188 if (!ether_addr_equal(addr->sa_data, master->dev_addr)) {
Jiri Pirkoa748ee22010-04-01 21:22:09 +0000189 err = dev_uc_add(master, addr->sa_data);
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800190 if (err < 0)
191 return err;
192 }
193
Joe Perches8feedbb2012-05-08 18:56:57 +0000194 if (!ether_addr_equal(dev->dev_addr, master->dev_addr))
Jiri Pirkoa748ee22010-04-01 21:22:09 +0000195 dev_uc_del(master, dev->dev_addr);
Lennert Buytenhekdf02c6f2008-11-10 21:53:12 -0800196
197out:
Joe Perchesd08f1612014-01-20 09:52:20 -0800198 ether_addr_copy(dev->dev_addr, addr->sa_data);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000199
200 return 0;
201}
202
Vivien Didelot11149532015-08-13 12:52:17 -0400203static int dsa_bridge_check_vlan_range(struct dsa_switch *ds,
204 const struct net_device *bridge,
205 u16 vid_begin, u16 vid_end)
206{
207 struct dsa_slave_priv *p;
208 struct net_device *dev, *vlan_br;
209 DECLARE_BITMAP(members, DSA_MAX_PORTS);
210 DECLARE_BITMAP(untagged, DSA_MAX_PORTS);
211 u16 vid;
212 int member, err;
213
214 if (!ds->drv->vlan_getnext || !vid_begin)
215 return -EOPNOTSUPP;
216
217 vid = vid_begin - 1;
218
219 do {
220 err = ds->drv->vlan_getnext(ds, &vid, members, untagged);
221 if (err)
222 break;
223
224 if (vid > vid_end)
225 break;
226
227 member = find_first_bit(members, DSA_MAX_PORTS);
228 if (member == DSA_MAX_PORTS)
229 continue;
230
231 dev = ds->ports[member];
232 p = netdev_priv(dev);
233 vlan_br = p->bridge_dev;
234 if (vlan_br == bridge)
235 continue;
236
237 netdev_dbg(vlan_br, "hardware VLAN %d already in use\n", vid);
238 return -EOPNOTSUPP;
239 } while (vid < vid_end);
240
241 return err == -ENOENT ? 0 : err;
242}
243
244static int dsa_slave_port_vlan_add(struct net_device *dev,
Jiri Pirkof8db8342015-09-24 10:02:42 +0200245 struct switchdev_obj *obj,
246 struct switchdev_trans *trans)
Vivien Didelot11149532015-08-13 12:52:17 -0400247{
248 struct switchdev_obj_vlan *vlan = &obj->u.vlan;
249 struct dsa_slave_priv *p = netdev_priv(dev);
250 struct dsa_switch *ds = p->parent;
251 u16 vid;
252 int err;
253
Jiri Pirkof8db8342015-09-24 10:02:42 +0200254 switch (trans->ph) {
Vivien Didelot11149532015-08-13 12:52:17 -0400255 case SWITCHDEV_TRANS_PREPARE:
256 if (!ds->drv->port_vlan_add || !ds->drv->port_pvid_set)
257 return -EOPNOTSUPP;
258
259 /* If the requested port doesn't belong to the same bridge as
260 * the VLAN members, fallback to software VLAN (hopefully).
261 */
262 err = dsa_bridge_check_vlan_range(ds, p->bridge_dev,
263 vlan->vid_begin,
264 vlan->vid_end);
265 if (err)
266 return err;
267 break;
268 case SWITCHDEV_TRANS_COMMIT:
269 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
270 err = ds->drv->port_vlan_add(ds, p->port, vid,
271 vlan->flags &
272 BRIDGE_VLAN_INFO_UNTAGGED);
273 if (!err && vlan->flags & BRIDGE_VLAN_INFO_PVID)
274 err = ds->drv->port_pvid_set(ds, p->port, vid);
275 if (err)
276 return err;
277 }
278 break;
279 default:
280 return -EOPNOTSUPP;
281 }
282
283 return 0;
284}
285
286static int dsa_slave_port_vlan_del(struct net_device *dev,
287 struct switchdev_obj *obj)
288{
289 struct switchdev_obj_vlan *vlan = &obj->u.vlan;
290 struct dsa_slave_priv *p = netdev_priv(dev);
291 struct dsa_switch *ds = p->parent;
292 u16 vid;
293 int err;
294
295 if (!ds->drv->port_vlan_del)
296 return -EOPNOTSUPP;
297
298 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
299 err = ds->drv->port_vlan_del(ds, p->port, vid);
300 if (err)
301 return err;
302 }
303
304 return 0;
305}
306
307static int dsa_slave_port_vlan_dump(struct net_device *dev,
308 struct switchdev_obj *obj)
309{
310 struct switchdev_obj_vlan *vlan = &obj->u.vlan;
311 struct dsa_slave_priv *p = netdev_priv(dev);
312 struct dsa_switch *ds = p->parent;
313 DECLARE_BITMAP(members, DSA_MAX_PORTS);
314 DECLARE_BITMAP(untagged, DSA_MAX_PORTS);
315 u16 pvid, vid = 0;
316 int err;
317
318 if (!ds->drv->vlan_getnext || !ds->drv->port_pvid_get)
319 return -EOPNOTSUPP;
320
321 err = ds->drv->port_pvid_get(ds, p->port, &pvid);
322 if (err)
323 return err;
324
325 for (;;) {
326 err = ds->drv->vlan_getnext(ds, &vid, members, untagged);
327 if (err)
328 break;
329
330 if (!test_bit(p->port, members))
331 continue;
332
333 memset(vlan, 0, sizeof(*vlan));
334 vlan->vid_begin = vlan->vid_end = vid;
335
336 if (vid == pvid)
337 vlan->flags |= BRIDGE_VLAN_INFO_PVID;
338
339 if (test_bit(p->port, untagged))
340 vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
341
342 err = obj->cb(dev, obj);
343 if (err)
344 break;
345 }
346
347 return err == -ENOENT ? 0 : err;
348}
349
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400350static int dsa_slave_port_fdb_add(struct net_device *dev,
Jiri Pirkof8db8342015-09-24 10:02:42 +0200351 struct switchdev_obj *obj,
352 struct switchdev_trans *trans)
David S. Millercdf09692015-08-11 12:00:37 -0700353{
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400354 struct switchdev_obj_fdb *fdb = &obj->u.fdb;
David S. Millercdf09692015-08-11 12:00:37 -0700355 struct dsa_slave_priv *p = netdev_priv(dev);
356 struct dsa_switch *ds = p->parent;
357 int ret = -EOPNOTSUPP;
358
Jiri Pirkof8db8342015-09-24 10:02:42 +0200359 if (trans->ph == SWITCHDEV_TRANS_PREPARE)
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400360 ret = ds->drv->port_fdb_add ? 0 : -EOPNOTSUPP;
Jiri Pirkof8db8342015-09-24 10:02:42 +0200361 else if (trans->ph == SWITCHDEV_TRANS_COMMIT)
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400362 ret = ds->drv->port_fdb_add(ds, p->port, fdb->addr, fdb->vid);
David S. Millercdf09692015-08-11 12:00:37 -0700363
364 return ret;
365}
366
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400367static int dsa_slave_port_fdb_del(struct net_device *dev,
368 struct switchdev_obj *obj)
David S. Millercdf09692015-08-11 12:00:37 -0700369{
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400370 struct switchdev_obj_fdb *fdb = &obj->u.fdb;
David S. Millercdf09692015-08-11 12:00:37 -0700371 struct dsa_slave_priv *p = netdev_priv(dev);
372 struct dsa_switch *ds = p->parent;
373 int ret = -EOPNOTSUPP;
374
Vivien Didelot2a778e12015-08-10 09:09:49 -0400375 if (ds->drv->port_fdb_del)
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400376 ret = ds->drv->port_fdb_del(ds, p->port, fdb->addr, fdb->vid);
David S. Millercdf09692015-08-11 12:00:37 -0700377
378 return ret;
379}
380
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400381static int dsa_slave_port_fdb_dump(struct net_device *dev,
382 struct switchdev_obj *obj)
David S. Millercdf09692015-08-11 12:00:37 -0700383{
384 struct dsa_slave_priv *p = netdev_priv(dev);
385 struct dsa_switch *ds = p->parent;
386 unsigned char addr[ETH_ALEN] = { 0 };
Vivien Didelot2a778e12015-08-10 09:09:49 -0400387 u16 vid = 0;
David S. Millercdf09692015-08-11 12:00:37 -0700388 int ret;
389
Vivien Didelot2a778e12015-08-10 09:09:49 -0400390 if (!ds->drv->port_fdb_getnext)
David S. Millercdf09692015-08-11 12:00:37 -0700391 return -EOPNOTSUPP;
392
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400393 for (;;) {
David S. Millercdf09692015-08-11 12:00:37 -0700394 bool is_static;
395
Vivien Didelot2a778e12015-08-10 09:09:49 -0400396 ret = ds->drv->port_fdb_getnext(ds, p->port, addr, &vid,
397 &is_static);
David S. Millercdf09692015-08-11 12:00:37 -0700398 if (ret < 0)
399 break;
400
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400401 obj->u.fdb.addr = addr;
402 obj->u.fdb.vid = vid;
403 obj->u.fdb.ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
David S. Millercdf09692015-08-11 12:00:37 -0700404
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400405 ret = obj->cb(dev, obj);
David S. Millercdf09692015-08-11 12:00:37 -0700406 if (ret < 0)
407 break;
408 }
409
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400410 return ret == -ENOENT ? 0 : ret;
David S. Millercdf09692015-08-11 12:00:37 -0700411}
412
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000413static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
414{
415 struct dsa_slave_priv *p = netdev_priv(dev);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000416
417 if (p->phy != NULL)
Richard Cochran28b04112010-07-17 08:48:55 +0000418 return phy_mii_ioctl(p->phy, ifr, cmd);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000419
420 return -EOPNOTSUPP;
421}
422
Florian Fainellib73adef2015-02-24 13:15:33 -0800423/* Return a bitmask of all ports being currently bridged within a given bridge
424 * device. Note that on leave, the mask will still return the bitmask of ports
425 * currently bridged, prior to port removal, and this is exactly what we want.
426 */
427static u32 dsa_slave_br_port_mask(struct dsa_switch *ds,
428 struct net_device *bridge)
429{
430 struct dsa_slave_priv *p;
431 unsigned int port;
432 u32 mask = 0;
433
434 for (port = 0; port < DSA_MAX_PORTS; port++) {
Guenter Roeckd79d2102015-02-24 23:02:02 -0800435 if (!dsa_is_port_initialized(ds, port))
Florian Fainellib73adef2015-02-24 13:15:33 -0800436 continue;
437
438 p = netdev_priv(ds->ports[port]);
439
440 if (ds->ports[port]->priv_flags & IFF_BRIDGE_PORT &&
441 p->bridge_dev == bridge)
442 mask |= 1 << port;
443 }
444
445 return mask;
446}
447
448static int dsa_slave_stp_update(struct net_device *dev, u8 state)
449{
450 struct dsa_slave_priv *p = netdev_priv(dev);
451 struct dsa_switch *ds = p->parent;
452 int ret = -EOPNOTSUPP;
453
454 if (ds->drv->port_stp_update)
455 ret = ds->drv->port_stp_update(ds, p->port, state);
456
457 return ret;
458}
459
Scott Feldman35636062015-05-10 09:47:51 -0700460static int dsa_slave_port_attr_set(struct net_device *dev,
Jiri Pirko7ea6eb32015-09-24 10:02:41 +0200461 struct switchdev_attr *attr,
462 struct switchdev_trans *trans)
Scott Feldman35636062015-05-10 09:47:51 -0700463{
464 int ret = 0;
465
466 switch (attr->id) {
467 case SWITCHDEV_ATTR_PORT_STP_STATE:
Jiri Pirkof8db8342015-09-24 10:02:42 +0200468 if (trans->ph == SWITCHDEV_TRANS_COMMIT)
Scott Feldman42275bd2015-05-13 11:16:50 -0700469 ret = dsa_slave_stp_update(dev, attr->u.stp_state);
Scott Feldman35636062015-05-10 09:47:51 -0700470 break;
471 default:
472 ret = -EOPNOTSUPP;
473 break;
474 }
475
476 return ret;
477}
478
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400479static int dsa_slave_port_obj_add(struct net_device *dev,
Jiri Pirko7ea6eb32015-09-24 10:02:41 +0200480 struct switchdev_obj *obj,
481 struct switchdev_trans *trans)
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400482{
483 int err;
484
485 /* For the prepare phase, ensure the full set of changes is feasable in
486 * one go in order to signal a failure properly. If an operation is not
487 * supported, return -EOPNOTSUPP.
488 */
489
490 switch (obj->id) {
491 case SWITCHDEV_OBJ_PORT_FDB:
Jiri Pirkof8db8342015-09-24 10:02:42 +0200492 err = dsa_slave_port_fdb_add(dev, obj, trans);
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400493 break;
Vivien Didelot11149532015-08-13 12:52:17 -0400494 case SWITCHDEV_OBJ_PORT_VLAN:
Jiri Pirkof8db8342015-09-24 10:02:42 +0200495 err = dsa_slave_port_vlan_add(dev, obj, trans);
Vivien Didelot11149532015-08-13 12:52:17 -0400496 break;
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400497 default:
498 err = -EOPNOTSUPP;
499 break;
500 }
501
502 return err;
503}
504
505static int dsa_slave_port_obj_del(struct net_device *dev,
506 struct switchdev_obj *obj)
507{
508 int err;
509
510 switch (obj->id) {
511 case SWITCHDEV_OBJ_PORT_FDB:
512 err = dsa_slave_port_fdb_del(dev, obj);
513 break;
Vivien Didelot11149532015-08-13 12:52:17 -0400514 case SWITCHDEV_OBJ_PORT_VLAN:
515 err = dsa_slave_port_vlan_del(dev, obj);
516 break;
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400517 default:
518 err = -EOPNOTSUPP;
519 break;
520 }
521
522 return err;
523}
524
525static int dsa_slave_port_obj_dump(struct net_device *dev,
526 struct switchdev_obj *obj)
527{
528 int err;
529
530 switch (obj->id) {
531 case SWITCHDEV_OBJ_PORT_FDB:
532 err = dsa_slave_port_fdb_dump(dev, obj);
533 break;
Vivien Didelot11149532015-08-13 12:52:17 -0400534 case SWITCHDEV_OBJ_PORT_VLAN:
535 err = dsa_slave_port_vlan_dump(dev, obj);
536 break;
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400537 default:
538 err = -EOPNOTSUPP;
539 break;
540 }
541
542 return err;
543}
544
Florian Fainellib73adef2015-02-24 13:15:33 -0800545static int dsa_slave_bridge_port_join(struct net_device *dev,
546 struct net_device *br)
547{
548 struct dsa_slave_priv *p = netdev_priv(dev);
549 struct dsa_switch *ds = p->parent;
550 int ret = -EOPNOTSUPP;
551
552 p->bridge_dev = br;
553
554 if (ds->drv->port_join_bridge)
555 ret = ds->drv->port_join_bridge(ds, p->port,
556 dsa_slave_br_port_mask(ds, br));
557
558 return ret;
559}
560
561static int dsa_slave_bridge_port_leave(struct net_device *dev)
562{
563 struct dsa_slave_priv *p = netdev_priv(dev);
564 struct dsa_switch *ds = p->parent;
565 int ret = -EOPNOTSUPP;
566
567
568 if (ds->drv->port_leave_bridge)
569 ret = ds->drv->port_leave_bridge(ds, p->port,
570 dsa_slave_br_port_mask(ds, p->bridge_dev));
571
572 p->bridge_dev = NULL;
573
574 /* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
575 * so allow it to be in BR_STATE_FORWARDING to be kept functional
576 */
577 dsa_slave_stp_update(dev, BR_STATE_FORWARDING);
578
579 return ret;
580}
581
Scott Feldmanf8e20a92015-05-10 09:47:49 -0700582static int dsa_slave_port_attr_get(struct net_device *dev,
583 struct switchdev_attr *attr)
Florian Fainellib73adef2015-02-24 13:15:33 -0800584{
585 struct dsa_slave_priv *p = netdev_priv(dev);
586 struct dsa_switch *ds = p->parent;
587
Scott Feldmanf8e20a92015-05-10 09:47:49 -0700588 switch (attr->id) {
589 case SWITCHDEV_ATTR_PORT_PARENT_ID:
Scott Feldman42275bd2015-05-13 11:16:50 -0700590 attr->u.ppid.id_len = sizeof(ds->index);
591 memcpy(&attr->u.ppid.id, &ds->index, attr->u.ppid.id_len);
Scott Feldmanf8e20a92015-05-10 09:47:49 -0700592 break;
593 default:
594 return -EOPNOTSUPP;
595 }
Florian Fainellib73adef2015-02-24 13:15:33 -0800596
597 return 0;
598}
599
Florian Fainelli04ff53f2015-07-31 11:42:57 -0700600static inline netdev_tx_t dsa_netpoll_send_skb(struct dsa_slave_priv *p,
601 struct sk_buff *skb)
602{
603#ifdef CONFIG_NET_POLL_CONTROLLER
604 if (p->netpoll)
605 netpoll_send_skb(p->netpoll, skb);
606#else
607 BUG();
608#endif
609 return NETDEV_TX_OK;
610}
611
Florian Fainelli3e8a72d2014-08-27 17:04:46 -0700612static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
613{
614 struct dsa_slave_priv *p = netdev_priv(dev);
Florian Fainelli4ed70ce2015-07-31 11:42:56 -0700615 struct sk_buff *nskb;
Florian Fainelli3e8a72d2014-08-27 17:04:46 -0700616
Florian Fainelli4ed70ce2015-07-31 11:42:56 -0700617 dev->stats.tx_packets++;
618 dev->stats.tx_bytes += skb->len;
Florian Fainelli3e8a72d2014-08-27 17:04:46 -0700619
Florian Fainelli4ed70ce2015-07-31 11:42:56 -0700620 /* Transmit function may have to reallocate the original SKB */
621 nskb = p->xmit(skb, dev);
622 if (!nskb)
623 return NETDEV_TX_OK;
Florian Fainelli5aed85c2014-08-27 17:04:52 -0700624
Florian Fainelli04ff53f2015-07-31 11:42:57 -0700625 /* SKB for netpoll still need to be mangled with the protocol-specific
626 * tag to be successfully transmitted
627 */
628 if (unlikely(netpoll_tx_running(dev)))
629 return dsa_netpoll_send_skb(p, nskb);
630
Florian Fainelli4ed70ce2015-07-31 11:42:56 -0700631 /* Queue the SKB for transmission on the parent interface, but
632 * do not modify its EtherType
633 */
634 nskb->dev = p->parent->dst->master_netdev;
635 dev_queue_xmit(nskb);
Florian Fainelli5aed85c2014-08-27 17:04:52 -0700636
637 return NETDEV_TX_OK;
638}
639
Florian Fainelli4ed70ce2015-07-31 11:42:56 -0700640static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff *skb,
641 struct net_device *dev)
642{
643 /* Just return the original SKB */
644 return skb;
645}
646
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000647
648/* ethtool operations *******************************************************/
649static int
650dsa_slave_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
651{
652 struct dsa_slave_priv *p = netdev_priv(dev);
653 int err;
654
655 err = -EOPNOTSUPP;
656 if (p->phy != NULL) {
657 err = phy_read_status(p->phy);
658 if (err == 0)
659 err = phy_ethtool_gset(p->phy, cmd);
660 }
661
662 return err;
663}
664
665static int
666dsa_slave_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
667{
668 struct dsa_slave_priv *p = netdev_priv(dev);
669
670 if (p->phy != NULL)
671 return phy_ethtool_sset(p->phy, cmd);
672
673 return -EOPNOTSUPP;
674}
675
676static void dsa_slave_get_drvinfo(struct net_device *dev,
677 struct ethtool_drvinfo *drvinfo)
678{
Jiri Pirko7826d432013-01-06 00:44:26 +0000679 strlcpy(drvinfo->driver, "dsa", sizeof(drvinfo->driver));
680 strlcpy(drvinfo->version, dsa_driver_version, sizeof(drvinfo->version));
681 strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
682 strlcpy(drvinfo->bus_info, "platform", sizeof(drvinfo->bus_info));
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000683}
684
Guenter Roeck3d762a02014-10-29 10:45:04 -0700685static int dsa_slave_get_regs_len(struct net_device *dev)
686{
687 struct dsa_slave_priv *p = netdev_priv(dev);
688 struct dsa_switch *ds = p->parent;
689
690 if (ds->drv->get_regs_len)
691 return ds->drv->get_regs_len(ds, p->port);
692
693 return -EOPNOTSUPP;
694}
695
696static void
697dsa_slave_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p)
698{
699 struct dsa_slave_priv *p = netdev_priv(dev);
700 struct dsa_switch *ds = p->parent;
701
702 if (ds->drv->get_regs)
703 ds->drv->get_regs(ds, p->port, regs, _p);
704}
705
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000706static int dsa_slave_nway_reset(struct net_device *dev)
707{
708 struct dsa_slave_priv *p = netdev_priv(dev);
709
710 if (p->phy != NULL)
711 return genphy_restart_aneg(p->phy);
712
713 return -EOPNOTSUPP;
714}
715
716static u32 dsa_slave_get_link(struct net_device *dev)
717{
718 struct dsa_slave_priv *p = netdev_priv(dev);
719
720 if (p->phy != NULL) {
721 genphy_update_link(p->phy);
722 return p->phy->link;
723 }
724
725 return -EOPNOTSUPP;
726}
727
Guenter Roeck6793abb2014-10-29 10:45:01 -0700728static int dsa_slave_get_eeprom_len(struct net_device *dev)
729{
730 struct dsa_slave_priv *p = netdev_priv(dev);
731 struct dsa_switch *ds = p->parent;
732
733 if (ds->pd->eeprom_len)
734 return ds->pd->eeprom_len;
735
736 if (ds->drv->get_eeprom_len)
737 return ds->drv->get_eeprom_len(ds);
738
739 return 0;
740}
741
742static int dsa_slave_get_eeprom(struct net_device *dev,
743 struct ethtool_eeprom *eeprom, u8 *data)
744{
745 struct dsa_slave_priv *p = netdev_priv(dev);
746 struct dsa_switch *ds = p->parent;
747
748 if (ds->drv->get_eeprom)
749 return ds->drv->get_eeprom(ds, eeprom, data);
750
751 return -EOPNOTSUPP;
752}
753
754static int dsa_slave_set_eeprom(struct net_device *dev,
755 struct ethtool_eeprom *eeprom, u8 *data)
756{
757 struct dsa_slave_priv *p = netdev_priv(dev);
758 struct dsa_switch *ds = p->parent;
759
760 if (ds->drv->set_eeprom)
761 return ds->drv->set_eeprom(ds, eeprom, data);
762
763 return -EOPNOTSUPP;
764}
765
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000766static void dsa_slave_get_strings(struct net_device *dev,
767 uint32_t stringset, uint8_t *data)
768{
769 struct dsa_slave_priv *p = netdev_priv(dev);
770 struct dsa_switch *ds = p->parent;
771
772 if (stringset == ETH_SS_STATS) {
773 int len = ETH_GSTRING_LEN;
774
775 strncpy(data, "tx_packets", len);
776 strncpy(data + len, "tx_bytes", len);
777 strncpy(data + 2 * len, "rx_packets", len);
778 strncpy(data + 3 * len, "rx_bytes", len);
779 if (ds->drv->get_strings != NULL)
780 ds->drv->get_strings(ds, p->port, data + 4 * len);
781 }
782}
783
784static void dsa_slave_get_ethtool_stats(struct net_device *dev,
785 struct ethtool_stats *stats,
786 uint64_t *data)
787{
788 struct dsa_slave_priv *p = netdev_priv(dev);
789 struct dsa_switch *ds = p->parent;
790
791 data[0] = p->dev->stats.tx_packets;
792 data[1] = p->dev->stats.tx_bytes;
793 data[2] = p->dev->stats.rx_packets;
794 data[3] = p->dev->stats.rx_bytes;
795 if (ds->drv->get_ethtool_stats != NULL)
796 ds->drv->get_ethtool_stats(ds, p->port, data + 4);
797}
798
799static int dsa_slave_get_sset_count(struct net_device *dev, int sset)
800{
801 struct dsa_slave_priv *p = netdev_priv(dev);
802 struct dsa_switch *ds = p->parent;
803
804 if (sset == ETH_SS_STATS) {
805 int count;
806
807 count = 4;
808 if (ds->drv->get_sset_count != NULL)
809 count += ds->drv->get_sset_count(ds);
810
811 return count;
812 }
813
814 return -EOPNOTSUPP;
815}
816
Florian Fainelli19e57c42014-09-18 17:31:24 -0700817static void dsa_slave_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
818{
819 struct dsa_slave_priv *p = netdev_priv(dev);
820 struct dsa_switch *ds = p->parent;
821
822 if (ds->drv->get_wol)
823 ds->drv->get_wol(ds, p->port, w);
824}
825
826static int dsa_slave_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
827{
828 struct dsa_slave_priv *p = netdev_priv(dev);
829 struct dsa_switch *ds = p->parent;
830 int ret = -EOPNOTSUPP;
831
832 if (ds->drv->set_wol)
833 ret = ds->drv->set_wol(ds, p->port, w);
834
835 return ret;
836}
837
Florian Fainelli79052882014-09-24 17:05:21 -0700838static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e)
839{
840 struct dsa_slave_priv *p = netdev_priv(dev);
841 struct dsa_switch *ds = p->parent;
842 int ret;
843
844 if (!ds->drv->set_eee)
845 return -EOPNOTSUPP;
846
847 ret = ds->drv->set_eee(ds, p->port, p->phy, e);
848 if (ret)
849 return ret;
850
851 if (p->phy)
852 ret = phy_ethtool_set_eee(p->phy, e);
853
854 return ret;
855}
856
857static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
858{
859 struct dsa_slave_priv *p = netdev_priv(dev);
860 struct dsa_switch *ds = p->parent;
861 int ret;
862
863 if (!ds->drv->get_eee)
864 return -EOPNOTSUPP;
865
866 ret = ds->drv->get_eee(ds, p->port, e);
867 if (ret)
868 return ret;
869
870 if (p->phy)
871 ret = phy_ethtool_get_eee(p->phy, e);
872
873 return ret;
874}
875
Florian Fainelli04ff53f2015-07-31 11:42:57 -0700876#ifdef CONFIG_NET_POLL_CONTROLLER
877static int dsa_slave_netpoll_setup(struct net_device *dev,
878 struct netpoll_info *ni)
879{
880 struct dsa_slave_priv *p = netdev_priv(dev);
881 struct dsa_switch *ds = p->parent;
882 struct net_device *master = ds->dst->master_netdev;
883 struct netpoll *netpoll;
884 int err = 0;
885
886 netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL);
887 if (!netpoll)
888 return -ENOMEM;
889
890 err = __netpoll_setup(netpoll, master);
891 if (err) {
892 kfree(netpoll);
893 goto out;
894 }
895
896 p->netpoll = netpoll;
897out:
898 return err;
899}
900
901static void dsa_slave_netpoll_cleanup(struct net_device *dev)
902{
903 struct dsa_slave_priv *p = netdev_priv(dev);
904 struct netpoll *netpoll = p->netpoll;
905
906 if (!netpoll)
907 return;
908
909 p->netpoll = NULL;
910
911 __netpoll_free_async(netpoll);
912}
913
914static void dsa_slave_poll_controller(struct net_device *dev)
915{
916}
917#endif
918
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000919static const struct ethtool_ops dsa_slave_ethtool_ops = {
920 .get_settings = dsa_slave_get_settings,
921 .set_settings = dsa_slave_set_settings,
922 .get_drvinfo = dsa_slave_get_drvinfo,
Guenter Roeck3d762a02014-10-29 10:45:04 -0700923 .get_regs_len = dsa_slave_get_regs_len,
924 .get_regs = dsa_slave_get_regs,
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000925 .nway_reset = dsa_slave_nway_reset,
926 .get_link = dsa_slave_get_link,
Guenter Roeck6793abb2014-10-29 10:45:01 -0700927 .get_eeprom_len = dsa_slave_get_eeprom_len,
928 .get_eeprom = dsa_slave_get_eeprom,
929 .set_eeprom = dsa_slave_set_eeprom,
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000930 .get_strings = dsa_slave_get_strings,
931 .get_ethtool_stats = dsa_slave_get_ethtool_stats,
932 .get_sset_count = dsa_slave_get_sset_count,
Florian Fainelli19e57c42014-09-18 17:31:24 -0700933 .set_wol = dsa_slave_set_wol,
934 .get_wol = dsa_slave_get_wol,
Florian Fainelli79052882014-09-24 17:05:21 -0700935 .set_eee = dsa_slave_set_eee,
936 .get_eee = dsa_slave_get_eee,
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000937};
938
Florian Fainelli3e8a72d2014-08-27 17:04:46 -0700939static const struct net_device_ops dsa_slave_netdev_ops = {
Stephen Hemmingerd442ad42009-01-06 16:45:26 -0800940 .ndo_open = dsa_slave_open,
941 .ndo_stop = dsa_slave_close,
Florian Fainelli3e8a72d2014-08-27 17:04:46 -0700942 .ndo_start_xmit = dsa_slave_xmit,
Stephen Hemmingerd442ad42009-01-06 16:45:26 -0800943 .ndo_change_rx_flags = dsa_slave_change_rx_flags,
944 .ndo_set_rx_mode = dsa_slave_set_rx_mode,
Stephen Hemmingerd442ad42009-01-06 16:45:26 -0800945 .ndo_set_mac_address = dsa_slave_set_mac_address,
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400946 .ndo_fdb_add = switchdev_port_fdb_add,
947 .ndo_fdb_del = switchdev_port_fdb_del,
948 .ndo_fdb_dump = switchdev_port_fdb_dump,
Stephen Hemmingerd442ad42009-01-06 16:45:26 -0800949 .ndo_do_ioctl = dsa_slave_ioctl,
Nicolas Dichtelabd2be02015-04-02 17:07:08 +0200950 .ndo_get_iflink = dsa_slave_get_iflink,
Florian Fainelli04ff53f2015-07-31 11:42:57 -0700951#ifdef CONFIG_NET_POLL_CONTROLLER
952 .ndo_netpoll_setup = dsa_slave_netpoll_setup,
953 .ndo_netpoll_cleanup = dsa_slave_netpoll_cleanup,
954 .ndo_poll_controller = dsa_slave_poll_controller,
955#endif
Vivien Didelot11149532015-08-13 12:52:17 -0400956 .ndo_bridge_getlink = switchdev_port_bridge_getlink,
957 .ndo_bridge_setlink = switchdev_port_bridge_setlink,
958 .ndo_bridge_dellink = switchdev_port_bridge_dellink,
Scott Feldman98237d42015-03-15 21:07:15 -0700959};
960
Jiri Pirko9d47c0a2015-05-10 09:47:47 -0700961static const struct switchdev_ops dsa_slave_switchdev_ops = {
Scott Feldmanf8e20a92015-05-10 09:47:49 -0700962 .switchdev_port_attr_get = dsa_slave_port_attr_get,
Scott Feldman35636062015-05-10 09:47:51 -0700963 .switchdev_port_attr_set = dsa_slave_port_attr_set,
Vivien Didelotba14d9e2015-08-10 09:09:53 -0400964 .switchdev_port_obj_add = dsa_slave_port_obj_add,
965 .switchdev_port_obj_del = dsa_slave_port_obj_del,
966 .switchdev_port_obj_dump = dsa_slave_port_obj_dump,
Stephen Hemmingerd442ad42009-01-06 16:45:26 -0800967};
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000968
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -0700969static void dsa_slave_adjust_link(struct net_device *dev)
970{
971 struct dsa_slave_priv *p = netdev_priv(dev);
Florian Fainelliec9436b2014-08-27 17:04:53 -0700972 struct dsa_switch *ds = p->parent;
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -0700973 unsigned int status_changed = 0;
974
975 if (p->old_link != p->phy->link) {
976 status_changed = 1;
977 p->old_link = p->phy->link;
978 }
979
980 if (p->old_duplex != p->phy->duplex) {
981 status_changed = 1;
982 p->old_duplex = p->phy->duplex;
983 }
984
985 if (p->old_pause != p->phy->pause) {
986 status_changed = 1;
987 p->old_pause = p->phy->pause;
988 }
989
Florian Fainelliec9436b2014-08-27 17:04:53 -0700990 if (ds->drv->adjust_link && status_changed)
991 ds->drv->adjust_link(ds, p->port, p->phy);
992
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -0700993 if (status_changed)
994 phy_print_status(p->phy);
995}
996
Florian Fainellice31b312014-08-27 17:04:54 -0700997static int dsa_slave_fixed_link_update(struct net_device *dev,
998 struct fixed_phy_status *status)
999{
1000 struct dsa_slave_priv *p = netdev_priv(dev);
1001 struct dsa_switch *ds = p->parent;
1002
1003 if (ds->drv->fixed_link_update)
1004 ds->drv->fixed_link_update(ds, p->port, status);
1005
1006 return 0;
1007}
1008
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001009/* slave device setup *******************************************************/
Florian Fainellic305c162015-03-10 16:57:12 -07001010static int dsa_slave_phy_connect(struct dsa_slave_priv *p,
Florian Fainellicd28a1a2015-03-10 16:57:13 -07001011 struct net_device *slave_dev,
1012 int addr)
Florian Fainellic305c162015-03-10 16:57:12 -07001013{
1014 struct dsa_switch *ds = p->parent;
1015
Florian Fainellicd28a1a2015-03-10 16:57:13 -07001016 p->phy = ds->slave_mii_bus->phy_map[addr];
Florian Fainellic305c162015-03-10 16:57:12 -07001017 if (!p->phy)
1018 return -ENODEV;
1019
1020 /* Use already configured phy mode */
Florian Fainelli211c5042015-08-08 12:58:57 -07001021 if (p->phy_interface == PHY_INTERFACE_MODE_NA)
1022 p->phy_interface = p->phy->interface;
Florian Fainellic305c162015-03-10 16:57:12 -07001023 phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
1024 p->phy_interface);
1025
1026 return 0;
1027}
1028
Florian Fainelli9697f1c2014-12-11 12:49:16 -08001029static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -07001030 struct net_device *slave_dev)
1031{
1032 struct dsa_switch *ds = p->parent;
1033 struct dsa_chip_data *cd = ds->pd;
1034 struct device_node *phy_dn, *port_dn;
Florian Fainellice31b312014-08-27 17:04:54 -07001035 bool phy_is_fixed = false;
Florian Fainelli68195632014-09-19 13:07:54 -07001036 u32 phy_flags = 0;
Guenter Roeck19334922015-02-16 21:23:51 -08001037 int mode, ret;
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -07001038
1039 port_dn = cd->port_dn[p->port];
Guenter Roeck19334922015-02-16 21:23:51 -08001040 mode = of_get_phy_mode(port_dn);
1041 if (mode < 0)
1042 mode = PHY_INTERFACE_MODE_NA;
1043 p->phy_interface = mode;
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -07001044
1045 phy_dn = of_parse_phandle(port_dn, "phy-handle", 0);
1046 if (of_phy_is_fixed_link(port_dn)) {
1047 /* In the case of a fixed PHY, the DT node associated
1048 * to the fixed PHY is the Port DT node
1049 */
1050 ret = of_phy_register_fixed_link(port_dn);
1051 if (ret) {
Joe Perchesa2ae6002014-11-09 16:32:46 -08001052 netdev_err(slave_dev, "failed to register fixed PHY\n");
Florian Fainelli9697f1c2014-12-11 12:49:16 -08001053 return ret;
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -07001054 }
Florian Fainellice31b312014-08-27 17:04:54 -07001055 phy_is_fixed = true;
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -07001056 phy_dn = port_dn;
1057 }
1058
Florian Fainelli68195632014-09-19 13:07:54 -07001059 if (ds->drv->get_phy_flags)
1060 phy_flags = ds->drv->get_phy_flags(ds, p->port);
1061
Florian Fainellicd28a1a2015-03-10 16:57:13 -07001062 if (phy_dn) {
1063 ret = of_mdio_parse_addr(&slave_dev->dev, phy_dn);
1064 /* If this PHY address is part of phys_mii_mask, which means
1065 * that we need to divert reads and writes to/from it, then we
1066 * want to bind this device using the slave MII bus created by
1067 * DSA to make that happen.
1068 */
Florian Fainelli96026d02015-03-14 13:21:59 -07001069 if (!phy_is_fixed && ret >= 0 &&
1070 (ds->phys_mii_mask & (1 << ret))) {
Florian Fainellicd28a1a2015-03-10 16:57:13 -07001071 ret = dsa_slave_phy_connect(p, slave_dev, ret);
1072 if (ret)
1073 return ret;
1074 } else {
1075 p->phy = of_phy_connect(slave_dev, phy_dn,
1076 dsa_slave_adjust_link,
1077 phy_flags,
1078 p->phy_interface);
1079 }
1080 }
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -07001081
Florian Fainellice31b312014-08-27 17:04:54 -07001082 if (p->phy && phy_is_fixed)
1083 fixed_phy_set_link_update(p->phy, dsa_slave_fixed_link_update);
1084
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -07001085 /* We could not connect to a designated PHY, so use the switch internal
1086 * MDIO bus instead
1087 */
Andrew Lunnb31f65f2014-11-05 19:47:28 +01001088 if (!p->phy) {
Florian Fainellicd28a1a2015-03-10 16:57:13 -07001089 ret = dsa_slave_phy_connect(p, slave_dev, p->port);
Florian Fainellic305c162015-03-10 16:57:12 -07001090 if (ret)
1091 return ret;
Andrew Lunnb31f65f2014-11-05 19:47:28 +01001092 } else {
Joe Perchesa2ae6002014-11-09 16:32:46 -08001093 netdev_info(slave_dev, "attached PHY at address %d [%s]\n",
1094 p->phy->addr, p->phy->drv->name);
Andrew Lunnb31f65f2014-11-05 19:47:28 +01001095 }
Florian Fainelli9697f1c2014-12-11 12:49:16 -08001096
1097 return 0;
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -07001098}
1099
Andrew Lunn448b4482015-05-06 01:09:56 +02001100static struct lock_class_key dsa_slave_netdev_xmit_lock_key;
1101static void dsa_slave_set_lockdep_class_one(struct net_device *dev,
1102 struct netdev_queue *txq,
1103 void *_unused)
1104{
1105 lockdep_set_class(&txq->_xmit_lock,
1106 &dsa_slave_netdev_xmit_lock_key);
1107}
1108
Florian Fainelli24462542014-09-18 17:31:22 -07001109int dsa_slave_suspend(struct net_device *slave_dev)
1110{
1111 struct dsa_slave_priv *p = netdev_priv(slave_dev);
1112
Florian Fainelli24462542014-09-18 17:31:22 -07001113 if (p->phy) {
1114 phy_stop(p->phy);
1115 p->old_pause = -1;
1116 p->old_link = -1;
1117 p->old_duplex = -1;
1118 phy_suspend(p->phy);
1119 }
1120
1121 return 0;
1122}
1123
1124int dsa_slave_resume(struct net_device *slave_dev)
1125{
1126 struct dsa_slave_priv *p = netdev_priv(slave_dev);
1127
1128 netif_device_attach(slave_dev);
1129
1130 if (p->phy) {
1131 phy_resume(p->phy);
1132 phy_start(p->phy);
1133 }
1134
1135 return 0;
1136}
1137
Guenter Roeckd87d6f42015-02-24 13:15:32 -08001138int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
1139 int port, char *name)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001140{
Lennert Buytenheke84665c2009-03-20 09:52:09 +00001141 struct net_device *master = ds->dst->master_netdev;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001142 struct net_device *slave_dev;
1143 struct dsa_slave_priv *p;
1144 int ret;
1145
Tom Gundersenc835a672014-07-14 16:37:24 +02001146 slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name,
1147 NET_NAME_UNKNOWN, ether_setup);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001148 if (slave_dev == NULL)
Guenter Roeckd87d6f42015-02-24 13:15:32 -08001149 return -ENOMEM;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001150
1151 slave_dev->features = master->vlan_features;
Wilfried Klaebe7ad24ea2014-05-11 00:12:32 +00001152 slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
Bjørn Mork2fcc8002013-08-30 18:08:46 +02001153 eth_hw_addr_inherit(slave_dev, master);
Phil Sutter0a5f1072015-08-18 10:30:41 +02001154 slave_dev->priv_flags |= IFF_NO_QUEUE;
Florian Fainelli3e8a72d2014-08-27 17:04:46 -07001155 slave_dev->netdev_ops = &dsa_slave_netdev_ops;
Jiri Pirko9d47c0a2015-05-10 09:47:47 -07001156 slave_dev->switchdev_ops = &dsa_slave_switchdev_ops;
Stephen Hemmingerd442ad42009-01-06 16:45:26 -08001157
Andrew Lunn448b4482015-05-06 01:09:56 +02001158 netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one,
1159 NULL);
1160
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001161 SET_NETDEV_DEV(slave_dev, parent);
Florian Fainellibd474972014-08-27 17:04:50 -07001162 slave_dev->dev.of_node = ds->pd->port_dn[port];
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001163 slave_dev->vlan_features = master->vlan_features;
1164
1165 p = netdev_priv(slave_dev);
1166 p->dev = slave_dev;
1167 p->parent = ds;
1168 p->port = port;
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -07001169
Alexander Duyck50753142014-09-15 13:00:19 -04001170 switch (ds->dst->tag_protocol) {
1171#ifdef CONFIG_NET_DSA_TAG_DSA
1172 case DSA_TAG_PROTO_DSA:
1173 p->xmit = dsa_netdev_ops.xmit;
1174 break;
1175#endif
1176#ifdef CONFIG_NET_DSA_TAG_EDSA
1177 case DSA_TAG_PROTO_EDSA:
1178 p->xmit = edsa_netdev_ops.xmit;
1179 break;
1180#endif
1181#ifdef CONFIG_NET_DSA_TAG_TRAILER
1182 case DSA_TAG_PROTO_TRAILER:
1183 p->xmit = trailer_netdev_ops.xmit;
1184 break;
1185#endif
1186#ifdef CONFIG_NET_DSA_TAG_BRCM
1187 case DSA_TAG_PROTO_BRCM:
1188 p->xmit = brcm_netdev_ops.xmit;
1189 break;
1190#endif
1191 default:
1192 p->xmit = dsa_slave_notag_xmit;
1193 break;
1194 }
1195
Florian Fainelli0d8bcdd2014-08-27 17:04:51 -07001196 p->old_pause = -1;
1197 p->old_link = -1;
1198 p->old_duplex = -1;
1199
Florian Fainelli9697f1c2014-12-11 12:49:16 -08001200 ret = dsa_slave_phy_setup(p, slave_dev);
1201 if (ret) {
1202 free_netdev(slave_dev);
Guenter Roeckd87d6f42015-02-24 13:15:32 -08001203 return ret;
Florian Fainelli9697f1c2014-12-11 12:49:16 -08001204 }
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001205
Guenter Roeckd87d6f42015-02-24 13:15:32 -08001206 ds->ports[port] = slave_dev;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001207 ret = register_netdev(slave_dev);
1208 if (ret) {
Joe Perchesa2ae6002014-11-09 16:32:46 -08001209 netdev_err(master, "error %d registering interface %s\n",
1210 ret, slave_dev->name);
Florian Fainelli9697f1c2014-12-11 12:49:16 -08001211 phy_disconnect(p->phy);
Guenter Roeckd87d6f42015-02-24 13:15:32 -08001212 ds->ports[port] = NULL;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001213 free_netdev(slave_dev);
Guenter Roeckd87d6f42015-02-24 13:15:32 -08001214 return ret;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001215 }
1216
1217 netif_carrier_off(slave_dev);
1218
Guenter Roeckd87d6f42015-02-24 13:15:32 -08001219 return 0;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001220}
Florian Fainellib73adef2015-02-24 13:15:33 -08001221
1222static bool dsa_slave_dev_check(struct net_device *dev)
1223{
1224 return dev->netdev_ops == &dsa_slave_netdev_ops;
1225}
1226
1227static int dsa_slave_master_changed(struct net_device *dev)
1228{
1229 struct net_device *master = netdev_master_upper_dev_get(dev);
Guenter Roeckb06b1072015-03-25 08:08:37 -07001230 struct dsa_slave_priv *p = netdev_priv(dev);
Florian Fainellib73adef2015-02-24 13:15:33 -08001231 int err = 0;
1232
1233 if (master && master->rtnl_link_ops &&
1234 !strcmp(master->rtnl_link_ops->kind, "bridge"))
1235 err = dsa_slave_bridge_port_join(dev, master);
Guenter Roeckb06b1072015-03-25 08:08:37 -07001236 else if (dsa_port_is_bridged(p))
Florian Fainellib73adef2015-02-24 13:15:33 -08001237 err = dsa_slave_bridge_port_leave(dev);
1238
1239 return err;
1240}
1241
1242int dsa_slave_netdevice_event(struct notifier_block *unused,
1243 unsigned long event, void *ptr)
1244{
1245 struct net_device *dev;
1246 int err = 0;
1247
1248 switch (event) {
1249 case NETDEV_CHANGEUPPER:
1250 dev = netdev_notifier_info_to_dev(ptr);
1251 if (!dsa_slave_dev_check(dev))
1252 goto out;
1253
1254 err = dsa_slave_master_changed(dev);
1255 if (err)
1256 netdev_warn(dev, "failed to reflect master change\n");
1257
1258 break;
1259 }
1260
1261out:
1262 return NOTIFY_DONE;
1263}