aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa/dsa.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-08 21:40:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-08 21:40:54 -0400
commit35a9ad8af0bb0fa3525e6d0d20e32551d226f38e (patch)
tree15b4b33206818886d9cff371fd2163e073b70568 /net/dsa/dsa.c
parentd5935b07da53f74726e2a65dd4281d0f2c70e5d4 (diff)
parent64b1f00a0830e1c53874067273a096b228d83d36 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: "Most notable changes in here: 1) By far the biggest accomplishment, thanks to a large range of contributors, is the addition of multi-send for transmit. This is the result of discussions back in Chicago, and the hard work of several individuals. Now, when the ->ndo_start_xmit() method of a driver sees skb->xmit_more as true, it can choose to defer the doorbell telling the driver to start processing the new TX queue entires. skb->xmit_more means that the generic networking is guaranteed to call the driver immediately with another SKB to send. There is logic added to the qdisc layer to dequeue multiple packets at a time, and the handling mis-predicted offloads in software is now done with no locks held. Finally, pktgen is extended to have a "burst" parameter that can be used to test a multi-send implementation. Several drivers have xmit_more support: i40e, igb, ixgbe, mlx4, virtio_net Adding support is almost trivial, so export more drivers to support this optimization soon. I want to thank, in no particular or implied order, Jesper Dangaard Brouer, Eric Dumazet, Alexander Duyck, Tom Herbert, Jamal Hadi Salim, John Fastabend, Florian Westphal, Daniel Borkmann, David Tat, Hannes Frederic Sowa, and Rusty Russell. 2) PTP and timestamping support in bnx2x, from Michal Kalderon. 3) Allow adjusting the rx_copybreak threshold for a driver via ethtool, and add rx_copybreak support to enic driver. From Govindarajulu Varadarajan. 4) Significant enhancements to the generic PHY layer and the bcm7xxx driver in particular (EEE support, auto power down, etc.) from Florian Fainelli. 5) Allow raw buffers to be used for flow dissection, allowing drivers to determine the optimal "linear pull" size for devices that DMA into pools of pages. The objective is to get exactly the necessary amount of headers into the linear SKB area pre-pulled, but no more. The new interface drivers use is eth_get_headlen(). From WANG Cong, with driver conversions (several had their own by-hand duplicated implementations) by Alexander Duyck and Eric Dumazet. 6) Support checksumming more smoothly and efficiently for encapsulations, and add "foo over UDP" facility. From Tom Herbert. 7) Add Broadcom SF2 switch driver to DSA layer, from Florian Fainelli. 8) eBPF now can load programs via a system call and has an extensive testsuite. Alexei Starovoitov and Daniel Borkmann. 9) Major overhaul of the packet scheduler to use RCU in several major areas such as the classifiers and rate estimators. From John Fastabend. 10) Add driver for Intel FM10000 Ethernet Switch, from Alexander Duyck. 11) Rearrange TCP_SKB_CB() to reduce cache line misses, from Eric Dumazet. 12) Add Datacenter TCP congestion control algorithm support, From Florian Westphal. 13) Reorganize sk_buff so that __copy_skb_header() is significantly faster. From Eric Dumazet" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1558 commits) netlabel: directly return netlbl_unlabel_genl_init() net: add netdev_txq_bql_{enqueue, complete}_prefetchw() helpers net: description of dma_cookie cause make xmldocs warning cxgb4: clean up a type issue cxgb4: potential shift wrapping bug i40e: skb->xmit_more support net: fs_enet: Add NAPI TX net: fs_enet: Remove non NAPI RX r8169:add support for RTL8168EP net_sched: copy exts->type in tcf_exts_change() wimax: convert printk to pr_foo() af_unix: remove 0 assignment on static ipv6: Do not warn for informational ICMP messages, regardless of type. Update Intel Ethernet Driver maintainers list bridge: Save frag_max_size between PRE_ROUTING and POST_ROUTING tipc: fix bug in multicast congestion handling net: better IFF_XMIT_DST_RELEASE support net/mlx4_en: remove NETDEV_TX_BUSY 3c59x: fix bad split of cpu_to_le32(pci_map_single()) net: bcmgenet: fix Tx ring priority programming ...
Diffstat (limited to 'net/dsa/dsa.c')
-rw-r--r--net/dsa/dsa.c186
1 files changed, 148 insertions, 38 deletions
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 0a49632fac47..22f34cf4cb27 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -10,7 +10,6 @@
10 */ 10 */
11 11
12#include <linux/list.h> 12#include <linux/list.h>
13#include <linux/netdevice.h>
14#include <linux/platform_device.h> 13#include <linux/platform_device.h>
15#include <linux/slab.h> 14#include <linux/slab.h>
16#include <linux/module.h> 15#include <linux/module.h>
@@ -44,7 +43,7 @@ void unregister_switch_driver(struct dsa_switch_driver *drv)
44EXPORT_SYMBOL_GPL(unregister_switch_driver); 43EXPORT_SYMBOL_GPL(unregister_switch_driver);
45 44
46static struct dsa_switch_driver * 45static struct dsa_switch_driver *
47dsa_switch_probe(struct mii_bus *bus, int sw_addr, char **_name) 46dsa_switch_probe(struct device *host_dev, int sw_addr, char **_name)
48{ 47{
49 struct dsa_switch_driver *ret; 48 struct dsa_switch_driver *ret;
50 struct list_head *list; 49 struct list_head *list;
@@ -59,7 +58,7 @@ dsa_switch_probe(struct mii_bus *bus, int sw_addr, char **_name)
59 58
60 drv = list_entry(list, struct dsa_switch_driver, list); 59 drv = list_entry(list, struct dsa_switch_driver, list);
61 60
62 name = drv->probe(bus, sw_addr); 61 name = drv->probe(host_dev, sw_addr);
63 if (name != NULL) { 62 if (name != NULL) {
64 ret = drv; 63 ret = drv;
65 break; 64 break;
@@ -76,7 +75,7 @@ dsa_switch_probe(struct mii_bus *bus, int sw_addr, char **_name)
76/* basic switch operations **************************************************/ 75/* basic switch operations **************************************************/
77static struct dsa_switch * 76static struct dsa_switch *
78dsa_switch_setup(struct dsa_switch_tree *dst, int index, 77dsa_switch_setup(struct dsa_switch_tree *dst, int index,
79 struct device *parent, struct mii_bus *bus) 78 struct device *parent, struct device *host_dev)
80{ 79{
81 struct dsa_chip_data *pd = dst->pd->chip + index; 80 struct dsa_chip_data *pd = dst->pd->chip + index;
82 struct dsa_switch_driver *drv; 81 struct dsa_switch_driver *drv;
@@ -89,7 +88,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
89 /* 88 /*
90 * Probe for switch model. 89 * Probe for switch model.
91 */ 90 */
92 drv = dsa_switch_probe(bus, pd->sw_addr, &name); 91 drv = dsa_switch_probe(host_dev, pd->sw_addr, &name);
93 if (drv == NULL) { 92 if (drv == NULL) {
94 printk(KERN_ERR "%s[%d]: could not detect attached switch\n", 93 printk(KERN_ERR "%s[%d]: could not detect attached switch\n",
95 dst->master_netdev->name, index); 94 dst->master_netdev->name, index);
@@ -110,8 +109,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
110 ds->index = index; 109 ds->index = index;
111 ds->pd = dst->pd->chip + index; 110 ds->pd = dst->pd->chip + index;
112 ds->drv = drv; 111 ds->drv = drv;
113 ds->master_mii_bus = bus; 112 ds->master_dev = host_dev;
114
115 113
116 /* 114 /*
117 * Validate supplied switch configuration. 115 * Validate supplied switch configuration.
@@ -144,14 +142,44 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
144 goto out; 142 goto out;
145 } 143 }
146 144
145 /* Make the built-in MII bus mask match the number of ports,
146 * switch drivers can override this later
147 */
148 ds->phys_mii_mask = ds->phys_port_mask;
149
147 /* 150 /*
148 * If the CPU connects to this switch, set the switch tree 151 * If the CPU connects to this switch, set the switch tree
149 * tagging protocol to the preferred tagging format of this 152 * tagging protocol to the preferred tagging format of this
150 * switch. 153 * switch.
151 */ 154 */
152 if (ds->dst->cpu_switch == index) 155 if (dst->cpu_switch == index) {
153 ds->dst->tag_protocol = drv->tag_protocol; 156 switch (drv->tag_protocol) {
157#ifdef CONFIG_NET_DSA_TAG_DSA
158 case DSA_TAG_PROTO_DSA:
159 dst->rcv = dsa_netdev_ops.rcv;
160 break;
161#endif
162#ifdef CONFIG_NET_DSA_TAG_EDSA
163 case DSA_TAG_PROTO_EDSA:
164 dst->rcv = edsa_netdev_ops.rcv;
165 break;
166#endif
167#ifdef CONFIG_NET_DSA_TAG_TRAILER
168 case DSA_TAG_PROTO_TRAILER:
169 dst->rcv = trailer_netdev_ops.rcv;
170 break;
171#endif
172#ifdef CONFIG_NET_DSA_TAG_BRCM
173 case DSA_TAG_PROTO_BRCM:
174 dst->rcv = brcm_netdev_ops.rcv;
175 break;
176#endif
177 default:
178 break;
179 }
154 180
181 dst->tag_protocol = drv->tag_protocol;
182 }
155 183
156 /* 184 /*
157 * Do basic register setup. 185 * Do basic register setup.
@@ -210,6 +238,51 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
210{ 238{
211} 239}
212 240
241#ifdef CONFIG_PM_SLEEP
242static int dsa_switch_suspend(struct dsa_switch *ds)
243{
244 int i, ret = 0;
245
246 /* Suspend slave network devices */
247 for (i = 0; i < DSA_MAX_PORTS; i++) {
248 if (!(ds->phys_port_mask & (1 << i)))
249 continue;
250
251 ret = dsa_slave_suspend(ds->ports[i]);
252 if (ret)
253 return ret;
254 }
255
256 if (ds->drv->suspend)
257 ret = ds->drv->suspend(ds);
258
259 return ret;
260}
261
262static int dsa_switch_resume(struct dsa_switch *ds)
263{
264 int i, ret = 0;
265
266 if (ds->drv->resume)
267 ret = ds->drv->resume(ds);
268
269 if (ret)
270 return ret;
271
272 /* Resume slave network devices */
273 for (i = 0; i < DSA_MAX_PORTS; i++) {
274 if (!(ds->phys_port_mask & (1 << i)))
275 continue;
276
277 ret = dsa_slave_resume(ds->ports[i]);
278 if (ret)
279 return ret;
280 }
281
282 return 0;
283}
284#endif
285
213 286
214/* link polling *************************************************************/ 287/* link polling *************************************************************/
215static void dsa_link_poll_work(struct work_struct *ugly) 288static void dsa_link_poll_work(struct work_struct *ugly)
@@ -256,7 +329,7 @@ static struct device *dev_find_class(struct device *parent, char *class)
256 return device_find_child(parent, class, dev_is_class); 329 return device_find_child(parent, class, dev_is_class);
257} 330}
258 331
259static struct mii_bus *dev_to_mii_bus(struct device *dev) 332struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev)
260{ 333{
261 struct device *d; 334 struct device *d;
262 335
@@ -272,6 +345,7 @@ static struct mii_bus *dev_to_mii_bus(struct device *dev)
272 345
273 return NULL; 346 return NULL;
274} 347}
348EXPORT_SYMBOL_GPL(dsa_host_dev_to_mii_bus);
275 349
276static struct net_device *dev_to_net_device(struct device *dev) 350static struct net_device *dev_to_net_device(struct device *dev)
277{ 351{
@@ -410,7 +484,8 @@ static int dsa_of_probe(struct platform_device *pdev)
410 chip_index++; 484 chip_index++;
411 cd = &pd->chip[chip_index]; 485 cd = &pd->chip[chip_index];
412 486
413 cd->mii_bus = &mdio_bus->dev; 487 cd->of_node = child;
488 cd->host_dev = &mdio_bus->dev;
414 489
415 sw_addr = of_get_property(child, "reg", NULL); 490 sw_addr = of_get_property(child, "reg", NULL);
416 if (!sw_addr) 491 if (!sw_addr)
@@ -431,6 +506,8 @@ static int dsa_of_probe(struct platform_device *pdev)
431 if (!port_name) 506 if (!port_name)
432 continue; 507 continue;
433 508
509 cd->port_dn[port_index] = port;
510
434 cd->port_names[port_index] = kstrdup(port_name, 511 cd->port_names[port_index] = kstrdup(port_name,
435 GFP_KERNEL); 512 GFP_KERNEL);
436 if (!cd->port_names[port_index]) { 513 if (!cd->port_names[port_index]) {
@@ -534,17 +611,9 @@ static int dsa_probe(struct platform_device *pdev)
534 dst->cpu_port = -1; 611 dst->cpu_port = -1;
535 612
536 for (i = 0; i < pd->nr_chips; i++) { 613 for (i = 0; i < pd->nr_chips; i++) {
537 struct mii_bus *bus;
538 struct dsa_switch *ds; 614 struct dsa_switch *ds;
539 615
540 bus = dev_to_mii_bus(pd->chip[i].mii_bus); 616 ds = dsa_switch_setup(dst, i, &pdev->dev, pd->chip[i].host_dev);
541 if (bus == NULL) {
542 printk(KERN_ERR "%s[%d]: no mii bus found for "
543 "dsa switch\n", dev->name, i);
544 continue;
545 }
546
547 ds = dsa_switch_setup(dst, i, &pdev->dev, bus);
548 if (IS_ERR(ds)) { 617 if (IS_ERR(ds)) {
549 printk(KERN_ERR "%s[%d]: couldn't create dsa switch " 618 printk(KERN_ERR "%s[%d]: couldn't create dsa switch "
550 "instance (error %ld)\n", dev->name, i, 619 "instance (error %ld)\n", dev->name, i,
@@ -608,7 +677,62 @@ static void dsa_shutdown(struct platform_device *pdev)
608{ 677{
609} 678}
610 679
680static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
681 struct packet_type *pt, struct net_device *orig_dev)
682{
683 struct dsa_switch_tree *dst = dev->dsa_ptr;
684
685 if (unlikely(dst == NULL)) {
686 kfree_skb(skb);
687 return 0;
688 }
689
690 return dst->rcv(skb, dev, pt, orig_dev);
691}
692
693static struct packet_type dsa_pack_type __read_mostly = {
694 .type = cpu_to_be16(ETH_P_XDSA),
695 .func = dsa_switch_rcv,
696};
697
698#ifdef CONFIG_PM_SLEEP
699static int dsa_suspend(struct device *d)
700{
701 struct platform_device *pdev = to_platform_device(d);
702 struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
703 int i, ret = 0;
704
705 for (i = 0; i < dst->pd->nr_chips; i++) {
706 struct dsa_switch *ds = dst->ds[i];
707
708 if (ds != NULL)
709 ret = dsa_switch_suspend(ds);
710 }
711
712 return ret;
713}
714
715static int dsa_resume(struct device *d)
716{
717 struct platform_device *pdev = to_platform_device(d);
718 struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
719 int i, ret = 0;
720
721 for (i = 0; i < dst->pd->nr_chips; i++) {
722 struct dsa_switch *ds = dst->ds[i];
723
724 if (ds != NULL)
725 ret = dsa_switch_resume(ds);
726 }
727
728 return ret;
729}
730#endif
731
732static SIMPLE_DEV_PM_OPS(dsa_pm_ops, dsa_suspend, dsa_resume);
733
611static const struct of_device_id dsa_of_match_table[] = { 734static const struct of_device_id dsa_of_match_table[] = {
735 { .compatible = "brcm,bcm7445-switch-v4.0" },
612 { .compatible = "marvell,dsa", }, 736 { .compatible = "marvell,dsa", },
613 {} 737 {}
614}; 738};
@@ -622,6 +746,7 @@ static struct platform_driver dsa_driver = {
622 .name = "dsa", 746 .name = "dsa",
623 .owner = THIS_MODULE, 747 .owner = THIS_MODULE,
624 .of_match_table = dsa_of_match_table, 748 .of_match_table = dsa_of_match_table,
749 .pm = &dsa_pm_ops,
625 }, 750 },
626}; 751};
627 752
@@ -633,30 +758,15 @@ static int __init dsa_init_module(void)
633 if (rc) 758 if (rc)
634 return rc; 759 return rc;
635 760
636#ifdef CONFIG_NET_DSA_TAG_DSA 761 dev_add_pack(&dsa_pack_type);
637 dev_add_pack(&dsa_packet_type); 762
638#endif
639#ifdef CONFIG_NET_DSA_TAG_EDSA
640 dev_add_pack(&edsa_packet_type);
641#endif
642#ifdef CONFIG_NET_DSA_TAG_TRAILER
643 dev_add_pack(&trailer_packet_type);
644#endif
645 return 0; 763 return 0;
646} 764}
647module_init(dsa_init_module); 765module_init(dsa_init_module);
648 766
649static void __exit dsa_cleanup_module(void) 767static void __exit dsa_cleanup_module(void)
650{ 768{
651#ifdef CONFIG_NET_DSA_TAG_TRAILER 769 dev_remove_pack(&dsa_pack_type);
652 dev_remove_pack(&trailer_packet_type);
653#endif
654#ifdef CONFIG_NET_DSA_TAG_EDSA
655 dev_remove_pack(&edsa_packet_type);
656#endif
657#ifdef CONFIG_NET_DSA_TAG_DSA
658 dev_remove_pack(&dsa_packet_type);
659#endif
660 platform_driver_unregister(&dsa_driver); 770 platform_driver_unregister(&dsa_driver);
661} 771}
662module_exit(dsa_cleanup_module); 772module_exit(dsa_cleanup_module);