Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
slave.c
Go to the documentation of this file.
1 /*
2  * net/dsa/slave.c - Slave device handling
3  * Copyright (c) 2008-2009 Marvell Semiconductor
4  *
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>
12 #include <linux/netdevice.h>
13 #include <linux/etherdevice.h>
14 #include <linux/phy.h>
15 #include "dsa_priv.h"
16 
17 /* slave mii_bus handling ***************************************************/
18 static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg)
19 {
20  struct dsa_switch *ds = bus->priv;
21 
22  if (ds->phys_port_mask & (1 << addr))
23  return ds->drv->phy_read(ds, addr, reg);
24 
25  return 0xffff;
26 }
27 
28 static int dsa_slave_phy_write(struct mii_bus *bus, int addr, int reg, u16 val)
29 {
30  struct dsa_switch *ds = bus->priv;
31 
32  if (ds->phys_port_mask & (1 << addr))
33  return ds->drv->phy_write(ds, addr, reg, val);
34 
35  return 0;
36 }
37 
39 {
40  ds->slave_mii_bus->priv = (void *)ds;
41  ds->slave_mii_bus->name = "dsa slave smi";
42  ds->slave_mii_bus->read = dsa_slave_phy_read;
43  ds->slave_mii_bus->write = dsa_slave_phy_write;
44  snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "%s:%.2x",
45  ds->master_mii_bus->id, ds->pd->sw_addr);
46  ds->slave_mii_bus->parent = &ds->master_mii_bus->dev;
47 }
48 
49 
50 /* slave device handling ****************************************************/
51 static int dsa_slave_init(struct net_device *dev)
52 {
53  struct dsa_slave_priv *p = netdev_priv(dev);
54 
55  dev->iflink = p->parent->dst->master_netdev->ifindex;
56 
57  return 0;
58 }
59 
60 static int dsa_slave_open(struct net_device *dev)
61 {
62  struct dsa_slave_priv *p = netdev_priv(dev);
63  struct net_device *master = p->parent->dst->master_netdev;
64  int err;
65 
66  if (!(master->flags & IFF_UP))
67  return -ENETDOWN;
68 
69  if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) {
70  err = dev_uc_add(master, dev->dev_addr);
71  if (err < 0)
72  goto out;
73  }
74 
75  if (dev->flags & IFF_ALLMULTI) {
76  err = dev_set_allmulti(master, 1);
77  if (err < 0)
78  goto del_unicast;
79  }
80  if (dev->flags & IFF_PROMISC) {
81  err = dev_set_promiscuity(master, 1);
82  if (err < 0)
83  goto clear_allmulti;
84  }
85 
86  return 0;
87 
88 clear_allmulti:
89  if (dev->flags & IFF_ALLMULTI)
90  dev_set_allmulti(master, -1);
91 del_unicast:
92  if (!ether_addr_equal(dev->dev_addr, master->dev_addr))
93  dev_uc_del(master, dev->dev_addr);
94 out:
95  return err;
96 }
97 
98 static int dsa_slave_close(struct net_device *dev)
99 {
100  struct dsa_slave_priv *p = netdev_priv(dev);
101  struct net_device *master = p->parent->dst->master_netdev;
102 
103  dev_mc_unsync(master, dev);
104  dev_uc_unsync(master, dev);
105  if (dev->flags & IFF_ALLMULTI)
106  dev_set_allmulti(master, -1);
107  if (dev->flags & IFF_PROMISC)
108  dev_set_promiscuity(master, -1);
109 
110  if (!ether_addr_equal(dev->dev_addr, master->dev_addr))
111  dev_uc_del(master, dev->dev_addr);
112 
113  return 0;
114 }
115 
116 static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
117 {
118  struct dsa_slave_priv *p = netdev_priv(dev);
119  struct net_device *master = p->parent->dst->master_netdev;
120 
121  if (change & IFF_ALLMULTI)
122  dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1);
123  if (change & IFF_PROMISC)
124  dev_set_promiscuity(master, dev->flags & IFF_PROMISC ? 1 : -1);
125 }
126 
127 static void dsa_slave_set_rx_mode(struct net_device *dev)
128 {
129  struct dsa_slave_priv *p = netdev_priv(dev);
130  struct net_device *master = p->parent->dst->master_netdev;
131 
132  dev_mc_sync(master, dev);
133  dev_uc_sync(master, dev);
134 }
135 
136 static int dsa_slave_set_mac_address(struct net_device *dev, void *a)
137 {
138  struct dsa_slave_priv *p = netdev_priv(dev);
139  struct net_device *master = p->parent->dst->master_netdev;
140  struct sockaddr *addr = a;
141  int err;
142 
143  if (!is_valid_ether_addr(addr->sa_data))
144  return -EADDRNOTAVAIL;
145 
146  if (!(dev->flags & IFF_UP))
147  goto out;
148 
149  if (!ether_addr_equal(addr->sa_data, master->dev_addr)) {
150  err = dev_uc_add(master, addr->sa_data);
151  if (err < 0)
152  return err;
153  }
154 
155  if (!ether_addr_equal(dev->dev_addr, master->dev_addr))
156  dev_uc_del(master, dev->dev_addr);
157 
158 out:
159  memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
160 
161  return 0;
162 }
163 
164 static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
165 {
166  struct dsa_slave_priv *p = netdev_priv(dev);
167 
168  if (p->phy != NULL)
169  return phy_mii_ioctl(p->phy, ifr, cmd);
170 
171  return -EOPNOTSUPP;
172 }
173 
174 
175 /* ethtool operations *******************************************************/
176 static int
177 dsa_slave_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
178 {
179  struct dsa_slave_priv *p = netdev_priv(dev);
180  int err;
181 
182  err = -EOPNOTSUPP;
183  if (p->phy != NULL) {
184  err = phy_read_status(p->phy);
185  if (err == 0)
186  err = phy_ethtool_gset(p->phy, cmd);
187  }
188 
189  return err;
190 }
191 
192 static int
193 dsa_slave_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
194 {
195  struct dsa_slave_priv *p = netdev_priv(dev);
196 
197  if (p->phy != NULL)
198  return phy_ethtool_sset(p->phy, cmd);
199 
200  return -EOPNOTSUPP;
201 }
202 
203 static void dsa_slave_get_drvinfo(struct net_device *dev,
204  struct ethtool_drvinfo *drvinfo)
205 {
206  strncpy(drvinfo->driver, "dsa", 32);
207  strncpy(drvinfo->version, dsa_driver_version, 32);
208  strncpy(drvinfo->fw_version, "N/A", 32);
209  strncpy(drvinfo->bus_info, "platform", 32);
210 }
211 
212 static int dsa_slave_nway_reset(struct net_device *dev)
213 {
214  struct dsa_slave_priv *p = netdev_priv(dev);
215 
216  if (p->phy != NULL)
217  return genphy_restart_aneg(p->phy);
218 
219  return -EOPNOTSUPP;
220 }
221 
222 static u32 dsa_slave_get_link(struct net_device *dev)
223 {
224  struct dsa_slave_priv *p = netdev_priv(dev);
225 
226  if (p->phy != NULL) {
228  return p->phy->link;
229  }
230 
231  return -EOPNOTSUPP;
232 }
233 
234 static void dsa_slave_get_strings(struct net_device *dev,
235  uint32_t stringset, uint8_t *data)
236 {
237  struct dsa_slave_priv *p = netdev_priv(dev);
238  struct dsa_switch *ds = p->parent;
239 
240  if (stringset == ETH_SS_STATS) {
241  int len = ETH_GSTRING_LEN;
242 
243  strncpy(data, "tx_packets", len);
244  strncpy(data + len, "tx_bytes", len);
245  strncpy(data + 2 * len, "rx_packets", len);
246  strncpy(data + 3 * len, "rx_bytes", len);
247  if (ds->drv->get_strings != NULL)
248  ds->drv->get_strings(ds, p->port, data + 4 * len);
249  }
250 }
251 
252 static void dsa_slave_get_ethtool_stats(struct net_device *dev,
253  struct ethtool_stats *stats,
254  uint64_t *data)
255 {
256  struct dsa_slave_priv *p = netdev_priv(dev);
257  struct dsa_switch *ds = p->parent;
258 
259  data[0] = p->dev->stats.tx_packets;
260  data[1] = p->dev->stats.tx_bytes;
261  data[2] = p->dev->stats.rx_packets;
262  data[3] = p->dev->stats.rx_bytes;
263  if (ds->drv->get_ethtool_stats != NULL)
264  ds->drv->get_ethtool_stats(ds, p->port, data + 4);
265 }
266 
267 static int dsa_slave_get_sset_count(struct net_device *dev, int sset)
268 {
269  struct dsa_slave_priv *p = netdev_priv(dev);
270  struct dsa_switch *ds = p->parent;
271 
272  if (sset == ETH_SS_STATS) {
273  int count;
274 
275  count = 4;
276  if (ds->drv->get_sset_count != NULL)
277  count += ds->drv->get_sset_count(ds);
278 
279  return count;
280  }
281 
282  return -EOPNOTSUPP;
283 }
284 
285 static const struct ethtool_ops dsa_slave_ethtool_ops = {
286  .get_settings = dsa_slave_get_settings,
287  .set_settings = dsa_slave_set_settings,
288  .get_drvinfo = dsa_slave_get_drvinfo,
289  .nway_reset = dsa_slave_nway_reset,
290  .get_link = dsa_slave_get_link,
291  .get_strings = dsa_slave_get_strings,
292  .get_ethtool_stats = dsa_slave_get_ethtool_stats,
293  .get_sset_count = dsa_slave_get_sset_count,
294 };
295 
296 #ifdef CONFIG_NET_DSA_TAG_DSA
297 static const struct net_device_ops dsa_netdev_ops = {
298  .ndo_init = dsa_slave_init,
299  .ndo_open = dsa_slave_open,
300  .ndo_stop = dsa_slave_close,
301  .ndo_start_xmit = dsa_xmit,
302  .ndo_change_rx_flags = dsa_slave_change_rx_flags,
303  .ndo_set_rx_mode = dsa_slave_set_rx_mode,
304  .ndo_set_mac_address = dsa_slave_set_mac_address,
305  .ndo_do_ioctl = dsa_slave_ioctl,
306 };
307 #endif
308 #ifdef CONFIG_NET_DSA_TAG_EDSA
309 static const struct net_device_ops edsa_netdev_ops = {
310  .ndo_init = dsa_slave_init,
311  .ndo_open = dsa_slave_open,
312  .ndo_stop = dsa_slave_close,
313  .ndo_start_xmit = edsa_xmit,
314  .ndo_change_rx_flags = dsa_slave_change_rx_flags,
315  .ndo_set_rx_mode = dsa_slave_set_rx_mode,
316  .ndo_set_mac_address = dsa_slave_set_mac_address,
317  .ndo_do_ioctl = dsa_slave_ioctl,
318 };
319 #endif
320 #ifdef CONFIG_NET_DSA_TAG_TRAILER
321 static const struct net_device_ops trailer_netdev_ops = {
322  .ndo_init = dsa_slave_init,
323  .ndo_open = dsa_slave_open,
324  .ndo_stop = dsa_slave_close,
325  .ndo_start_xmit = trailer_xmit,
326  .ndo_change_rx_flags = dsa_slave_change_rx_flags,
327  .ndo_set_rx_mode = dsa_slave_set_rx_mode,
328  .ndo_set_mac_address = dsa_slave_set_mac_address,
329  .ndo_do_ioctl = dsa_slave_ioctl,
330 };
331 #endif
332 
333 /* slave device setup *******************************************************/
334 struct net_device *
335 dsa_slave_create(struct dsa_switch *ds, struct device *parent,
336  int port, char *name)
337 {
338  struct net_device *master = ds->dst->master_netdev;
339  struct net_device *slave_dev;
340  struct dsa_slave_priv *p;
341  int ret;
342 
343  slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv),
344  name, ether_setup);
345  if (slave_dev == NULL)
346  return slave_dev;
347 
348  slave_dev->features = master->vlan_features;
349  SET_ETHTOOL_OPS(slave_dev, &dsa_slave_ethtool_ops);
350  memcpy(slave_dev->dev_addr, master->dev_addr, ETH_ALEN);
351  slave_dev->tx_queue_len = 0;
352 
353  switch (ds->dst->tag_protocol) {
354 #ifdef CONFIG_NET_DSA_TAG_DSA
355  case htons(ETH_P_DSA):
356  slave_dev->netdev_ops = &dsa_netdev_ops;
357  break;
358 #endif
359 #ifdef CONFIG_NET_DSA_TAG_EDSA
360  case htons(ETH_P_EDSA):
361  slave_dev->netdev_ops = &edsa_netdev_ops;
362  break;
363 #endif
364 #ifdef CONFIG_NET_DSA_TAG_TRAILER
365  case htons(ETH_P_TRAILER):
366  slave_dev->netdev_ops = &trailer_netdev_ops;
367  break;
368 #endif
369  default:
370  BUG();
371  }
372 
373  SET_NETDEV_DEV(slave_dev, parent);
374  slave_dev->vlan_features = master->vlan_features;
375 
376  p = netdev_priv(slave_dev);
377  p->dev = slave_dev;
378  p->parent = ds;
379  p->port = port;
380  p->phy = ds->slave_mii_bus->phy_map[port];
381 
382  ret = register_netdev(slave_dev);
383  if (ret) {
384  printk(KERN_ERR "%s: error %d registering interface %s\n",
385  master->name, ret, slave_dev->name);
386  free_netdev(slave_dev);
387  return NULL;
388  }
389 
390  netif_carrier_off(slave_dev);
391 
392  if (p->phy != NULL) {
393  phy_attach(slave_dev, dev_name(&p->phy->dev),
395 
396  p->phy->autoneg = AUTONEG_ENABLE;
397  p->phy->speed = 0;
398  p->phy->duplex = 0;
399  p->phy->advertising = p->phy->supported | ADVERTISED_Autoneg;
400  phy_start_aneg(p->phy);
401  }
402 
403  return slave_dev;
404 }