1 /* 2 * net/dsa/dsa.c - Hardware switch handling 3 * Copyright (c) 2008-2009 Marvell Semiconductor 4 * Copyright (c) 2013 Florian Fainelli <florian@openwrt.org> 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/device.h> 13 #include <linux/list.h> 14 #include <linux/platform_device.h> 15 #include <linux/slab.h> 16 #include <linux/module.h> 17 #include <linux/of.h> 18 #include <linux/of_mdio.h> 19 #include <linux/of_platform.h> 20 #include <linux/of_net.h> 21 #include <linux/of_gpio.h> 22 #include <linux/netdevice.h> 23 #include <linux/sysfs.h> 24 #include <linux/phy_fixed.h> 25 #include <linux/gpio/consumer.h> 26 #include <linux/etherdevice.h> 27 #include <net/dsa.h> 28 #include "dsa_priv.h" 29 30 static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff *skb, 31 struct net_device *dev) 32 { 33 /* Just return the original SKB */ 34 return skb; 35 } 36 37 static const struct dsa_device_ops none_ops = { 38 .xmit = dsa_slave_notag_xmit, 39 .rcv = NULL, 40 }; 41 42 const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = { 43 #ifdef CONFIG_NET_DSA_TAG_DSA 44 [DSA_TAG_PROTO_DSA] = &dsa_netdev_ops, 45 #endif 46 #ifdef CONFIG_NET_DSA_TAG_EDSA 47 [DSA_TAG_PROTO_EDSA] = &edsa_netdev_ops, 48 #endif 49 #ifdef CONFIG_NET_DSA_TAG_TRAILER 50 [DSA_TAG_PROTO_TRAILER] = &trailer_netdev_ops, 51 #endif 52 #ifdef CONFIG_NET_DSA_TAG_BRCM 53 [DSA_TAG_PROTO_BRCM] = &brcm_netdev_ops, 54 #endif 55 #ifdef CONFIG_NET_DSA_TAG_QCA 56 [DSA_TAG_PROTO_QCA] = &qca_netdev_ops, 57 #endif 58 #ifdef CONFIG_NET_DSA_TAG_MTK 59 [DSA_TAG_PROTO_MTK] = &mtk_netdev_ops, 60 #endif 61 #ifdef CONFIG_NET_DSA_TAG_LAN9303 62 [DSA_TAG_PROTO_LAN9303] = &lan9303_netdev_ops, 63 #endif 64 [DSA_TAG_PROTO_NONE] = &none_ops, 65 }; 66 67 int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device *dev, 68 struct dsa_port *dport, int port) 69 { 70 struct device_node *port_dn = dport->dn; 71 struct phy_device *phydev; 72 int ret, mode; 73 74 if (of_phy_is_fixed_link(port_dn)) { 75 ret = of_phy_register_fixed_link(port_dn); 76 if (ret) { 77 dev_err(dev, "failed to register fixed PHY\n"); 78 return ret; 79 } 80 phydev = of_phy_find_device(port_dn); 81 82 mode = of_get_phy_mode(port_dn); 83 if (mode < 0) 84 mode = PHY_INTERFACE_MODE_NA; 85 phydev->interface = mode; 86 87 genphy_config_init(phydev); 88 genphy_read_status(phydev); 89 if (ds->ops->adjust_link) 90 ds->ops->adjust_link(ds, port, phydev); 91 92 put_device(&phydev->mdio.dev); 93 } 94 95 return 0; 96 } 97 98 const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol) 99 { 100 const struct dsa_device_ops *ops; 101 102 if (tag_protocol >= DSA_TAG_LAST) 103 return ERR_PTR(-EINVAL); 104 ops = dsa_device_ops[tag_protocol]; 105 106 if (!ops) 107 return ERR_PTR(-ENOPROTOOPT); 108 109 return ops; 110 } 111 112 int dsa_cpu_port_ethtool_setup(struct dsa_switch *ds) 113 { 114 struct net_device *master; 115 struct ethtool_ops *cpu_ops; 116 117 master = ds->dst->master_netdev; 118 if (ds->master_netdev) 119 master = ds->master_netdev; 120 121 cpu_ops = devm_kzalloc(ds->dev, sizeof(*cpu_ops), GFP_KERNEL); 122 if (!cpu_ops) 123 return -ENOMEM; 124 125 memcpy(&ds->dst->master_ethtool_ops, master->ethtool_ops, 126 sizeof(struct ethtool_ops)); 127 ds->dst->master_orig_ethtool_ops = master->ethtool_ops; 128 memcpy(cpu_ops, &ds->dst->master_ethtool_ops, 129 sizeof(struct ethtool_ops)); 130 dsa_cpu_port_ethtool_init(cpu_ops); 131 master->ethtool_ops = cpu_ops; 132 133 return 0; 134 } 135 136 void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds) 137 { 138 struct net_device *master; 139 140 master = ds->dst->master_netdev; 141 if (ds->master_netdev) 142 master = ds->master_netdev; 143 144 master->ethtool_ops = ds->dst->master_orig_ethtool_ops; 145 } 146 147 void dsa_cpu_dsa_destroy(struct dsa_port *port) 148 { 149 struct device_node *port_dn = port->dn; 150 151 if (of_phy_is_fixed_link(port_dn)) 152 of_phy_deregister_fixed_link(port_dn); 153 } 154 155 static int dev_is_class(struct device *dev, void *class) 156 { 157 if (dev->class != NULL && !strcmp(dev->class->name, class)) 158 return 1; 159 160 return 0; 161 } 162 163 static struct device *dev_find_class(struct device *parent, char *class) 164 { 165 if (dev_is_class(parent, class)) { 166 get_device(parent); 167 return parent; 168 } 169 170 return device_find_child(parent, class, dev_is_class); 171 } 172 173 struct net_device *dsa_dev_to_net_device(struct device *dev) 174 { 175 struct device *d; 176 177 d = dev_find_class(dev, "net"); 178 if (d != NULL) { 179 struct net_device *nd; 180 181 nd = to_net_dev(d); 182 dev_hold(nd); 183 put_device(d); 184 185 return nd; 186 } 187 188 return NULL; 189 } 190 EXPORT_SYMBOL_GPL(dsa_dev_to_net_device); 191 192 static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, 193 struct packet_type *pt, struct net_device *orig_dev) 194 { 195 struct dsa_switch_tree *dst = dev->dsa_ptr; 196 struct sk_buff *nskb = NULL; 197 198 if (unlikely(dst == NULL)) { 199 kfree_skb(skb); 200 return 0; 201 } 202 203 skb = skb_unshare(skb, GFP_ATOMIC); 204 if (!skb) 205 return 0; 206 207 nskb = dst->rcv(skb, dev, pt, orig_dev); 208 if (!nskb) { 209 kfree_skb(skb); 210 return 0; 211 } 212 213 skb = nskb; 214 skb_push(skb, ETH_HLEN); 215 skb->pkt_type = PACKET_HOST; 216 skb->protocol = eth_type_trans(skb, skb->dev); 217 218 skb->dev->stats.rx_packets++; 219 skb->dev->stats.rx_bytes += skb->len; 220 221 netif_receive_skb(skb); 222 223 return 0; 224 } 225 226 static struct packet_type dsa_pack_type __read_mostly = { 227 .type = cpu_to_be16(ETH_P_XDSA), 228 .func = dsa_switch_rcv, 229 }; 230 231 static int __init dsa_init_module(void) 232 { 233 int rc; 234 235 rc = dsa_slave_register_notifier(); 236 if (rc) 237 return rc; 238 239 rc = dsa_legacy_register(); 240 if (rc) 241 return rc; 242 243 dev_add_pack(&dsa_pack_type); 244 245 return 0; 246 } 247 module_init(dsa_init_module); 248 249 static void __exit dsa_cleanup_module(void) 250 { 251 dsa_slave_unregister_notifier(); 252 dev_remove_pack(&dsa_pack_type); 253 dsa_legacy_unregister(); 254 } 255 module_exit(dsa_cleanup_module); 256 257 MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>"); 258 MODULE_DESCRIPTION("Driver for Distributed Switch Architecture switch chips"); 259 MODULE_LICENSE("GPL"); 260 MODULE_ALIAS("platform:dsa"); 261