at v3.9-rc2 404 lines 10 kB view raw
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 ***************************************************/ 18static 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 28static 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 38void dsa_slave_mii_bus_init(struct dsa_switch *ds) 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, "dsa-%d:%.2x", 45 ds->index, ds->pd->sw_addr); 46 ds->slave_mii_bus->parent = &ds->master_mii_bus->dev; 47} 48 49 50/* slave device handling ****************************************************/ 51static 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 60static 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 88clear_allmulti: 89 if (dev->flags & IFF_ALLMULTI) 90 dev_set_allmulti(master, -1); 91del_unicast: 92 if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) 93 dev_uc_del(master, dev->dev_addr); 94out: 95 return err; 96} 97 98static 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 116static 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 127static 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 136static 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 158out: 159 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); 160 161 return 0; 162} 163 164static 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 *******************************************************/ 176static int 177dsa_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 192static int 193dsa_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 203static void dsa_slave_get_drvinfo(struct net_device *dev, 204 struct ethtool_drvinfo *drvinfo) 205{ 206 strlcpy(drvinfo->driver, "dsa", sizeof(drvinfo->driver)); 207 strlcpy(drvinfo->version, dsa_driver_version, sizeof(drvinfo->version)); 208 strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); 209 strlcpy(drvinfo->bus_info, "platform", sizeof(drvinfo->bus_info)); 210} 211 212static 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 222static 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) { 227 genphy_update_link(p->phy); 228 return p->phy->link; 229 } 230 231 return -EOPNOTSUPP; 232} 233 234static 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 252static 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 267static 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 285static 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 297static 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 309static 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 321static 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 *******************************************************/ 334struct net_device * 335dsa_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), 394 PHY_INTERFACE_MODE_GMII); 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}