diff options
50 files changed, 3417 insertions, 112 deletions
@@ -1856,7 +1856,7 @@ E: rfkoenig@immd4.informatik.uni-erlangen.de | |||
1856 | D: The Linux Support Team Erlangen | 1856 | D: The Linux Support Team Erlangen |
1857 | 1857 | ||
1858 | N: Andreas Koensgen | 1858 | N: Andreas Koensgen |
1859 | E: ajk@iehk.rwth-aachen.de | 1859 | E: ajk@comnets.uni-bremen.de |
1860 | D: 6pack driver for AX.25 | 1860 | D: 6pack driver for AX.25 |
1861 | 1861 | ||
1862 | N: Harald Koerfgen | 1862 | N: Harald Koerfgen |
diff --git a/Documentation/RCU/rculist_nulls.txt b/Documentation/RCU/rculist_nulls.txt index 93cb28d05dcd..18f9651ff23d 100644 --- a/Documentation/RCU/rculist_nulls.txt +++ b/Documentation/RCU/rculist_nulls.txt | |||
@@ -83,11 +83,12 @@ not detect it missed following items in original chain. | |||
83 | obj = kmem_cache_alloc(...); | 83 | obj = kmem_cache_alloc(...); |
84 | lock_chain(); // typically a spin_lock() | 84 | lock_chain(); // typically a spin_lock() |
85 | obj->key = key; | 85 | obj->key = key; |
86 | atomic_inc(&obj->refcnt); | ||
87 | /* | 86 | /* |
88 | * we need to make sure obj->key is updated before obj->next | 87 | * we need to make sure obj->key is updated before obj->next |
88 | * or obj->refcnt | ||
89 | */ | 89 | */ |
90 | smp_wmb(); | 90 | smp_wmb(); |
91 | atomic_set(&obj->refcnt, 1); | ||
91 | hlist_add_head_rcu(&obj->obj_node, list); | 92 | hlist_add_head_rcu(&obj->obj_node, list); |
92 | unlock_chain(); // typically a spin_unlock() | 93 | unlock_chain(); // typically a spin_unlock() |
93 | 94 | ||
@@ -159,6 +160,10 @@ out: | |||
159 | obj = kmem_cache_alloc(cachep); | 160 | obj = kmem_cache_alloc(cachep); |
160 | lock_chain(); // typically a spin_lock() | 161 | lock_chain(); // typically a spin_lock() |
161 | obj->key = key; | 162 | obj->key = key; |
163 | /* | ||
164 | * changes to obj->key must be visible before refcnt one | ||
165 | */ | ||
166 | smp_wmb(); | ||
162 | atomic_set(&obj->refcnt, 1); | 167 | atomic_set(&obj->refcnt, 1); |
163 | /* | 168 | /* |
164 | * insert obj in RCU way (readers might be traversing chain) | 169 | * insert obj in RCU way (readers might be traversing chain) |
diff --git a/Documentation/connector/cn_test.c b/Documentation/connector/cn_test.c index f688eba87704..6a5be5d5c8e4 100644 --- a/Documentation/connector/cn_test.c +++ b/Documentation/connector/cn_test.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * cn_test.c | 2 | * cn_test.c |
3 | * | 3 | * |
4 | * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 4 | * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -194,5 +194,5 @@ module_init(cn_test_init); | |||
194 | module_exit(cn_test_fini); | 194 | module_exit(cn_test_fini); |
195 | 195 | ||
196 | MODULE_LICENSE("GPL"); | 196 | MODULE_LICENSE("GPL"); |
197 | MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | 197 | MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); |
198 | MODULE_DESCRIPTION("Connector's test module"); | 198 | MODULE_DESCRIPTION("Connector's test module"); |
diff --git a/Documentation/connector/ucon.c b/Documentation/connector/ucon.c index d738cde2a8d5..c5092ad0ce4b 100644 --- a/Documentation/connector/ucon.c +++ b/Documentation/connector/ucon.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ucon.c | 2 | * ucon.c |
3 | * | 3 | * |
4 | * Copyright (c) 2004+ Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 4 | * Copyright (c) 2004+ Evgeniy Polyakov <zbr@ioremap.net> |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
diff --git a/Documentation/networking/6pack.txt b/Documentation/networking/6pack.txt index d0777a1200e1..8f339428fdf4 100644 --- a/Documentation/networking/6pack.txt +++ b/Documentation/networking/6pack.txt | |||
@@ -1,7 +1,7 @@ | |||
1 | This is the 6pack-mini-HOWTO, written by | 1 | This is the 6pack-mini-HOWTO, written by |
2 | 2 | ||
3 | Andreas Könsgen DG3KQ | 3 | Andreas Könsgen DG3KQ |
4 | Internet: ajk@iehk.rwth-aachen.de | 4 | Internet: ajk@comnets.uni-bremen.de |
5 | AMPR-net: dg3kq@db0pra.ampr.org | 5 | AMPR-net: dg3kq@db0pra.ampr.org |
6 | AX.25: dg3kq@db0ach.#nrw.deu.eu | 6 | AX.25: dg3kq@db0ach.#nrw.deu.eu |
7 | 7 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 18c3f0c41c95..ebc269152faf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -150,7 +150,7 @@ F: drivers/scsi/53c700* | |||
150 | 150 | ||
151 | 6PACK NETWORK DRIVER FOR AX.25 | 151 | 6PACK NETWORK DRIVER FOR AX.25 |
152 | P: Andreas Koensgen | 152 | P: Andreas Koensgen |
153 | M: ajk@iehk.rwth-aachen.de | 153 | M: ajk@comnets.uni-bremen.de |
154 | L: linux-hams@vger.kernel.org | 154 | L: linux-hams@vger.kernel.org |
155 | S: Maintained | 155 | S: Maintained |
156 | F: drivers/net/hamradio/6pack.c | 156 | F: drivers/net/hamradio/6pack.c |
@@ -1612,6 +1612,13 @@ S: Supported | |||
1612 | F: fs/configfs/ | 1612 | F: fs/configfs/ |
1613 | F: include/linux/configfs.h | 1613 | F: include/linux/configfs.h |
1614 | 1614 | ||
1615 | CONNECTOR | ||
1616 | P: Evgeniy Polyakov | ||
1617 | M: zbr@ioremap.net | ||
1618 | L: netdev@vger.kernel.org | ||
1619 | S: Maintained | ||
1620 | F: drivers/connector/ | ||
1621 | |||
1615 | CONTROL GROUPS (CGROUPS) | 1622 | CONTROL GROUPS (CGROUPS) |
1616 | P: Paul Menage | 1623 | P: Paul Menage |
1617 | M: menage@google.com | 1624 | M: menage@google.com |
@@ -4089,6 +4096,7 @@ L: netfilter@vger.kernel.org | |||
4089 | L: coreteam@netfilter.org | 4096 | L: coreteam@netfilter.org |
4090 | W: http://www.netfilter.org/ | 4097 | W: http://www.netfilter.org/ |
4091 | W: http://www.iptables.org/ | 4098 | W: http://www.iptables.org/ |
4099 | T: git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6.git | ||
4092 | S: Supported | 4100 | S: Supported |
4093 | F: include/linux/netfilter* | 4101 | F: include/linux/netfilter* |
4094 | F: include/linux/netfilter/ | 4102 | F: include/linux/netfilter/ |
@@ -5586,7 +5594,6 @@ S: Odd Fixes | |||
5586 | F: drivers/net/starfire* | 5594 | F: drivers/net/starfire* |
5587 | 5595 | ||
5588 | STARMODE RADIO IP (STRIP) PROTOCOL DRIVER | 5596 | STARMODE RADIO IP (STRIP) PROTOCOL DRIVER |
5589 | W: http://mosquitonet.Stanford.EDU/strip.html | ||
5590 | S: Orphan | 5597 | S: Orphan |
5591 | F: drivers/net/wireless/strip.c | 5598 | F: drivers/net/wireless/strip.c |
5592 | F: include/linux/if_strip.h | 5599 | F: include/linux/if_strip.h |
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c index c769ef269fb5..408c2af25d50 100644 --- a/drivers/connector/cn_queue.c +++ b/drivers/connector/cn_queue.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * cn_queue.c | 2 | * cn_queue.c |
3 | * | 3 | * |
4 | * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 4 | * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index fd336c5a9057..08b2500f21ec 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * connector.c | 2 | * connector.c |
3 | * | 3 | * |
4 | * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 4 | * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -33,7 +33,7 @@ | |||
33 | #include <net/sock.h> | 33 | #include <net/sock.h> |
34 | 34 | ||
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | 36 | MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); |
37 | MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector."); | 37 | MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector."); |
38 | 38 | ||
39 | static u32 cn_idx = CN_IDX_CONNECTOR; | 39 | static u32 cn_idx = CN_IDX_CONNECTOR; |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c155bd3ec9f1..b5a7513df4eb 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -1729,6 +1729,12 @@ config KS8842 | |||
1729 | help | 1729 | help |
1730 | This platform driver is for Micrel KSZ8842 chip. | 1730 | This platform driver is for Micrel KSZ8842 chip. |
1731 | 1731 | ||
1732 | config KS8851 | ||
1733 | tristate "Micrel KS8851 SPI" | ||
1734 | depends on SPI | ||
1735 | help | ||
1736 | SPI driver for Micrel KS8851 SPI attached network chip. | ||
1737 | |||
1732 | config VIA_RHINE | 1738 | config VIA_RHINE |
1733 | tristate "VIA Rhine support" | 1739 | tristate "VIA Rhine support" |
1734 | depends on NET_PCI && PCI | 1740 | depends on NET_PCI && PCI |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 4b58a59f211b..ead8cab3cfe1 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
@@ -88,6 +88,7 @@ obj-$(CONFIG_SKGE) += skge.o | |||
88 | obj-$(CONFIG_SKY2) += sky2.o | 88 | obj-$(CONFIG_SKY2) += sky2.o |
89 | obj-$(CONFIG_SKFP) += skfp/ | 89 | obj-$(CONFIG_SKFP) += skfp/ |
90 | obj-$(CONFIG_KS8842) += ks8842.o | 90 | obj-$(CONFIG_KS8842) += ks8842.o |
91 | obj-$(CONFIG_KS8851) += ks8851.o | ||
91 | obj-$(CONFIG_VIA_RHINE) += via-rhine.o | 92 | obj-$(CONFIG_VIA_RHINE) += via-rhine.o |
92 | obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o | 93 | obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o |
93 | obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o | 94 | obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o |
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig index 2895db13bfa4..c37ee9e6b67b 100644 --- a/drivers/net/arm/Kconfig +++ b/drivers/net/arm/Kconfig | |||
@@ -63,3 +63,11 @@ config IXP4XX_ETH | |||
63 | help | 63 | help |
64 | Say Y here if you want to use built-in Ethernet ports | 64 | Say Y here if you want to use built-in Ethernet ports |
65 | on IXP4xx processor. | 65 | on IXP4xx processor. |
66 | |||
67 | config W90P910_ETH | ||
68 | tristate "Nuvoton w90p910 Ethernet support" | ||
69 | depends on ARM && ARCH_W90X900 | ||
70 | select PHYLIB | ||
71 | help | ||
72 | Say Y here if you want to use built-in Ethernet ports | ||
73 | on w90p910 processor. | ||
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile index 811a3ccd14c1..303171f589e6 100644 --- a/drivers/net/arm/Makefile +++ b/drivers/net/arm/Makefile | |||
@@ -11,3 +11,4 @@ obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o | |||
11 | obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o | 11 | obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o |
12 | obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o | 12 | obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o |
13 | obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o | 13 | obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o |
14 | obj-$(CONFIG_W90P910_ETH) += w90p910_ether.o | ||
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c new file mode 100644 index 000000000000..616fb7985a34 --- /dev/null +++ b/drivers/net/arm/w90p910_ether.c | |||
@@ -0,0 +1,1105 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Nuvoton technology corporation. | ||
3 | * | ||
4 | * Wan ZongShun <mcuos.com@gmail.com> | ||
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;version 2 of the License. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/mii.h> | ||
15 | #include <linux/netdevice.h> | ||
16 | #include <linux/etherdevice.h> | ||
17 | #include <linux/skbuff.h> | ||
18 | #include <linux/ethtool.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/clk.h> | ||
21 | |||
22 | #define DRV_MODULE_NAME "w90p910-emc" | ||
23 | #define DRV_MODULE_VERSION "0.1" | ||
24 | |||
25 | /* Ethernet MAC Registers */ | ||
26 | #define REG_CAMCMR 0x00 | ||
27 | #define REG_CAMEN 0x04 | ||
28 | #define REG_CAMM_BASE 0x08 | ||
29 | #define REG_CAML_BASE 0x0c | ||
30 | #define REG_TXDLSA 0x88 | ||
31 | #define REG_RXDLSA 0x8C | ||
32 | #define REG_MCMDR 0x90 | ||
33 | #define REG_MIID 0x94 | ||
34 | #define REG_MIIDA 0x98 | ||
35 | #define REG_FFTCR 0x9C | ||
36 | #define REG_TSDR 0xa0 | ||
37 | #define REG_RSDR 0xa4 | ||
38 | #define REG_DMARFC 0xa8 | ||
39 | #define REG_MIEN 0xac | ||
40 | #define REG_MISTA 0xb0 | ||
41 | #define REG_CTXDSA 0xcc | ||
42 | #define REG_CTXBSA 0xd0 | ||
43 | #define REG_CRXDSA 0xd4 | ||
44 | #define REG_CRXBSA 0xd8 | ||
45 | |||
46 | /* mac controller bit */ | ||
47 | #define MCMDR_RXON 0x01 | ||
48 | #define MCMDR_ACP (0x01 << 3) | ||
49 | #define MCMDR_SPCRC (0x01 << 5) | ||
50 | #define MCMDR_TXON (0x01 << 8) | ||
51 | #define MCMDR_FDUP (0x01 << 18) | ||
52 | #define MCMDR_ENMDC (0x01 << 19) | ||
53 | #define MCMDR_OPMOD (0x01 << 20) | ||
54 | #define SWR (0x01 << 24) | ||
55 | |||
56 | /* cam command regiser */ | ||
57 | #define CAMCMR_AUP 0x01 | ||
58 | #define CAMCMR_AMP (0x01 << 1) | ||
59 | #define CAMCMR_ABP (0x01 << 2) | ||
60 | #define CAMCMR_CCAM (0x01 << 3) | ||
61 | #define CAMCMR_ECMP (0x01 << 4) | ||
62 | #define CAM0EN 0x01 | ||
63 | |||
64 | /* mac mii controller bit */ | ||
65 | #define MDCCR (0x0a << 20) | ||
66 | #define PHYAD (0x01 << 8) | ||
67 | #define PHYWR (0x01 << 16) | ||
68 | #define PHYBUSY (0x01 << 17) | ||
69 | #define PHYPRESP (0x01 << 18) | ||
70 | #define CAM_ENTRY_SIZE 0x08 | ||
71 | |||
72 | /* rx and tx status */ | ||
73 | #define TXDS_TXCP (0x01 << 19) | ||
74 | #define RXDS_CRCE (0x01 << 17) | ||
75 | #define RXDS_PTLE (0x01 << 19) | ||
76 | #define RXDS_RXGD (0x01 << 20) | ||
77 | #define RXDS_ALIE (0x01 << 21) | ||
78 | #define RXDS_RP (0x01 << 22) | ||
79 | |||
80 | /* mac interrupt status*/ | ||
81 | #define MISTA_EXDEF (0x01 << 19) | ||
82 | #define MISTA_TXBERR (0x01 << 24) | ||
83 | #define MISTA_TDU (0x01 << 23) | ||
84 | #define MISTA_RDU (0x01 << 10) | ||
85 | #define MISTA_RXBERR (0x01 << 11) | ||
86 | |||
87 | #define ENSTART 0x01 | ||
88 | #define ENRXINTR 0x01 | ||
89 | #define ENRXGD (0x01 << 4) | ||
90 | #define ENRXBERR (0x01 << 11) | ||
91 | #define ENTXINTR (0x01 << 16) | ||
92 | #define ENTXCP (0x01 << 18) | ||
93 | #define ENTXABT (0x01 << 21) | ||
94 | #define ENTXBERR (0x01 << 24) | ||
95 | #define ENMDC (0x01 << 19) | ||
96 | #define PHYBUSY (0x01 << 17) | ||
97 | #define MDCCR_VAL 0xa00000 | ||
98 | |||
99 | /* rx and tx owner bit */ | ||
100 | #define RX_OWEN_DMA (0x01 << 31) | ||
101 | #define RX_OWEN_CPU (~(0x03 << 30)) | ||
102 | #define TX_OWEN_DMA (0x01 << 31) | ||
103 | #define TX_OWEN_CPU (~(0x01 << 31)) | ||
104 | |||
105 | /* tx frame desc controller bit */ | ||
106 | #define MACTXINTEN 0x04 | ||
107 | #define CRCMODE 0x02 | ||
108 | #define PADDINGMODE 0x01 | ||
109 | |||
110 | /* fftcr controller bit */ | ||
111 | #define TXTHD (0x03 << 8) | ||
112 | #define BLENGTH (0x01 << 20) | ||
113 | |||
114 | /* global setting for driver */ | ||
115 | #define RX_DESC_SIZE 50 | ||
116 | #define TX_DESC_SIZE 10 | ||
117 | #define MAX_RBUFF_SZ 0x600 | ||
118 | #define MAX_TBUFF_SZ 0x600 | ||
119 | #define TX_TIMEOUT 50 | ||
120 | #define DELAY 1000 | ||
121 | #define CAM0 0x0 | ||
122 | |||
123 | static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg); | ||
124 | |||
125 | struct w90p910_rxbd { | ||
126 | unsigned int sl; | ||
127 | unsigned int buffer; | ||
128 | unsigned int reserved; | ||
129 | unsigned int next; | ||
130 | }; | ||
131 | |||
132 | struct w90p910_txbd { | ||
133 | unsigned int mode; | ||
134 | unsigned int buffer; | ||
135 | unsigned int sl; | ||
136 | unsigned int next; | ||
137 | }; | ||
138 | |||
139 | struct recv_pdesc { | ||
140 | struct w90p910_rxbd desclist[RX_DESC_SIZE]; | ||
141 | char recv_buf[RX_DESC_SIZE][MAX_RBUFF_SZ]; | ||
142 | }; | ||
143 | |||
144 | struct tran_pdesc { | ||
145 | struct w90p910_txbd desclist[TX_DESC_SIZE]; | ||
146 | char tran_buf[RX_DESC_SIZE][MAX_TBUFF_SZ]; | ||
147 | }; | ||
148 | |||
149 | struct w90p910_ether { | ||
150 | struct recv_pdesc *rdesc; | ||
151 | struct recv_pdesc *rdesc_phys; | ||
152 | struct tran_pdesc *tdesc; | ||
153 | struct tran_pdesc *tdesc_phys; | ||
154 | struct net_device_stats stats; | ||
155 | struct platform_device *pdev; | ||
156 | struct sk_buff *skb; | ||
157 | struct clk *clk; | ||
158 | struct clk *rmiiclk; | ||
159 | struct mii_if_info mii; | ||
160 | struct timer_list check_timer; | ||
161 | void __iomem *reg; | ||
162 | unsigned int rxirq; | ||
163 | unsigned int txirq; | ||
164 | unsigned int cur_tx; | ||
165 | unsigned int cur_rx; | ||
166 | unsigned int finish_tx; | ||
167 | unsigned int rx_packets; | ||
168 | unsigned int rx_bytes; | ||
169 | unsigned int start_tx_ptr; | ||
170 | unsigned int start_rx_ptr; | ||
171 | unsigned int linkflag; | ||
172 | spinlock_t lock; | ||
173 | }; | ||
174 | |||
175 | static void update_linkspeed_register(struct net_device *dev, | ||
176 | unsigned int speed, unsigned int duplex) | ||
177 | { | ||
178 | struct w90p910_ether *ether = netdev_priv(dev); | ||
179 | unsigned int val; | ||
180 | |||
181 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
182 | |||
183 | if (speed == SPEED_100) { | ||
184 | /* 100 full/half duplex */ | ||
185 | if (duplex == DUPLEX_FULL) { | ||
186 | val |= (MCMDR_OPMOD | MCMDR_FDUP); | ||
187 | } else { | ||
188 | val |= MCMDR_OPMOD; | ||
189 | val &= ~MCMDR_FDUP; | ||
190 | } | ||
191 | } else { | ||
192 | /* 10 full/half duplex */ | ||
193 | if (duplex == DUPLEX_FULL) { | ||
194 | val |= MCMDR_FDUP; | ||
195 | val &= ~MCMDR_OPMOD; | ||
196 | } else { | ||
197 | val &= ~(MCMDR_FDUP | MCMDR_OPMOD); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
202 | } | ||
203 | |||
204 | static void update_linkspeed(struct net_device *dev) | ||
205 | { | ||
206 | struct w90p910_ether *ether = netdev_priv(dev); | ||
207 | struct platform_device *pdev; | ||
208 | unsigned int bmsr, bmcr, lpa, speed, duplex; | ||
209 | |||
210 | pdev = ether->pdev; | ||
211 | |||
212 | if (!mii_link_ok(ðer->mii)) { | ||
213 | ether->linkflag = 0x0; | ||
214 | netif_carrier_off(dev); | ||
215 | dev_warn(&pdev->dev, "%s: Link down.\n", dev->name); | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | if (ether->linkflag == 1) | ||
220 | return; | ||
221 | |||
222 | bmsr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMSR); | ||
223 | bmcr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMCR); | ||
224 | |||
225 | if (bmcr & BMCR_ANENABLE) { | ||
226 | if (!(bmsr & BMSR_ANEGCOMPLETE)) | ||
227 | return; | ||
228 | |||
229 | lpa = w90p910_mdio_read(dev, ether->mii.phy_id, MII_LPA); | ||
230 | |||
231 | if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) | ||
232 | speed = SPEED_100; | ||
233 | else | ||
234 | speed = SPEED_10; | ||
235 | |||
236 | if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) | ||
237 | duplex = DUPLEX_FULL; | ||
238 | else | ||
239 | duplex = DUPLEX_HALF; | ||
240 | |||
241 | } else { | ||
242 | speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; | ||
243 | duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; | ||
244 | } | ||
245 | |||
246 | update_linkspeed_register(dev, speed, duplex); | ||
247 | |||
248 | dev_info(&pdev->dev, "%s: Link now %i-%s\n", dev->name, speed, | ||
249 | (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); | ||
250 | ether->linkflag = 0x01; | ||
251 | |||
252 | netif_carrier_on(dev); | ||
253 | } | ||
254 | |||
255 | static void w90p910_check_link(unsigned long dev_id) | ||
256 | { | ||
257 | struct net_device *dev = (struct net_device *) dev_id; | ||
258 | struct w90p910_ether *ether = netdev_priv(dev); | ||
259 | |||
260 | update_linkspeed(dev); | ||
261 | mod_timer(ðer->check_timer, jiffies + msecs_to_jiffies(1000)); | ||
262 | } | ||
263 | |||
264 | static void w90p910_write_cam(struct net_device *dev, | ||
265 | unsigned int x, unsigned char *pval) | ||
266 | { | ||
267 | struct w90p910_ether *ether = netdev_priv(dev); | ||
268 | unsigned int msw, lsw; | ||
269 | |||
270 | msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3]; | ||
271 | |||
272 | lsw = (pval[4] << 24) | (pval[5] << 16); | ||
273 | |||
274 | __raw_writel(lsw, ether->reg + REG_CAML_BASE + x * CAM_ENTRY_SIZE); | ||
275 | __raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE); | ||
276 | } | ||
277 | |||
278 | static void w90p910_init_desc(struct net_device *dev) | ||
279 | { | ||
280 | struct w90p910_ether *ether; | ||
281 | struct w90p910_txbd *tdesc, *tdesc_phys; | ||
282 | struct w90p910_rxbd *rdesc, *rdesc_phys; | ||
283 | unsigned int i, j; | ||
284 | |||
285 | ether = netdev_priv(dev); | ||
286 | |||
287 | ether->tdesc = (struct tran_pdesc *) | ||
288 | dma_alloc_coherent(NULL, sizeof(struct tran_pdesc), | ||
289 | (dma_addr_t *) ðer->tdesc_phys, GFP_KERNEL); | ||
290 | |||
291 | ether->rdesc = (struct recv_pdesc *) | ||
292 | dma_alloc_coherent(NULL, sizeof(struct recv_pdesc), | ||
293 | (dma_addr_t *) ðer->rdesc_phys, GFP_KERNEL); | ||
294 | |||
295 | for (i = 0; i < TX_DESC_SIZE; i++) { | ||
296 | tdesc = &(ether->tdesc->desclist[i]); | ||
297 | |||
298 | j = ((i + 1) / TX_DESC_SIZE); | ||
299 | |||
300 | if (j != 0) { | ||
301 | tdesc_phys = &(ether->tdesc_phys->desclist[0]); | ||
302 | ether->start_tx_ptr = (unsigned int)tdesc_phys; | ||
303 | tdesc->next = (unsigned int)ether->start_tx_ptr; | ||
304 | } else { | ||
305 | tdesc_phys = &(ether->tdesc_phys->desclist[i+1]); | ||
306 | tdesc->next = (unsigned int)tdesc_phys; | ||
307 | } | ||
308 | |||
309 | tdesc->buffer = (unsigned int)ether->tdesc_phys->tran_buf[i]; | ||
310 | tdesc->sl = 0; | ||
311 | tdesc->mode = 0; | ||
312 | } | ||
313 | |||
314 | for (i = 0; i < RX_DESC_SIZE; i++) { | ||
315 | rdesc = &(ether->rdesc->desclist[i]); | ||
316 | |||
317 | j = ((i + 1) / RX_DESC_SIZE); | ||
318 | |||
319 | if (j != 0) { | ||
320 | rdesc_phys = &(ether->rdesc_phys->desclist[0]); | ||
321 | ether->start_rx_ptr = (unsigned int)rdesc_phys; | ||
322 | rdesc->next = (unsigned int)ether->start_rx_ptr; | ||
323 | } else { | ||
324 | rdesc_phys = &(ether->rdesc_phys->desclist[i+1]); | ||
325 | rdesc->next = (unsigned int)rdesc_phys; | ||
326 | } | ||
327 | |||
328 | rdesc->sl = RX_OWEN_DMA; | ||
329 | rdesc->buffer = (unsigned int)ether->rdesc_phys->recv_buf[i]; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | static void w90p910_set_fifo_threshold(struct net_device *dev) | ||
334 | { | ||
335 | struct w90p910_ether *ether = netdev_priv(dev); | ||
336 | unsigned int val; | ||
337 | |||
338 | val = TXTHD | BLENGTH; | ||
339 | __raw_writel(val, ether->reg + REG_FFTCR); | ||
340 | } | ||
341 | |||
342 | static void w90p910_return_default_idle(struct net_device *dev) | ||
343 | { | ||
344 | struct w90p910_ether *ether = netdev_priv(dev); | ||
345 | unsigned int val; | ||
346 | |||
347 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
348 | val |= SWR; | ||
349 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
350 | } | ||
351 | |||
352 | static void w90p910_trigger_rx(struct net_device *dev) | ||
353 | { | ||
354 | struct w90p910_ether *ether = netdev_priv(dev); | ||
355 | |||
356 | __raw_writel(ENSTART, ether->reg + REG_RSDR); | ||
357 | } | ||
358 | |||
359 | static void w90p910_trigger_tx(struct net_device *dev) | ||
360 | { | ||
361 | struct w90p910_ether *ether = netdev_priv(dev); | ||
362 | |||
363 | __raw_writel(ENSTART, ether->reg + REG_TSDR); | ||
364 | } | ||
365 | |||
366 | static void w90p910_enable_mac_interrupt(struct net_device *dev) | ||
367 | { | ||
368 | struct w90p910_ether *ether = netdev_priv(dev); | ||
369 | unsigned int val; | ||
370 | |||
371 | val = ENTXINTR | ENRXINTR | ENRXGD | ENTXCP; | ||
372 | val |= ENTXBERR | ENRXBERR | ENTXABT; | ||
373 | |||
374 | __raw_writel(val, ether->reg + REG_MIEN); | ||
375 | } | ||
376 | |||
377 | static void w90p910_get_and_clear_int(struct net_device *dev, | ||
378 | unsigned int *val) | ||
379 | { | ||
380 | struct w90p910_ether *ether = netdev_priv(dev); | ||
381 | |||
382 | *val = __raw_readl(ether->reg + REG_MISTA); | ||
383 | __raw_writel(*val, ether->reg + REG_MISTA); | ||
384 | } | ||
385 | |||
386 | static void w90p910_set_global_maccmd(struct net_device *dev) | ||
387 | { | ||
388 | struct w90p910_ether *ether = netdev_priv(dev); | ||
389 | unsigned int val; | ||
390 | |||
391 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
392 | val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | ENMDC; | ||
393 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
394 | } | ||
395 | |||
396 | static void w90p910_enable_cam(struct net_device *dev) | ||
397 | { | ||
398 | struct w90p910_ether *ether = netdev_priv(dev); | ||
399 | unsigned int val; | ||
400 | |||
401 | w90p910_write_cam(dev, CAM0, dev->dev_addr); | ||
402 | |||
403 | val = __raw_readl(ether->reg + REG_CAMEN); | ||
404 | val |= CAM0EN; | ||
405 | __raw_writel(val, ether->reg + REG_CAMEN); | ||
406 | } | ||
407 | |||
408 | static void w90p910_enable_cam_command(struct net_device *dev) | ||
409 | { | ||
410 | struct w90p910_ether *ether = netdev_priv(dev); | ||
411 | unsigned int val; | ||
412 | |||
413 | val = CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AMP; | ||
414 | __raw_writel(val, ether->reg + REG_CAMCMR); | ||
415 | } | ||
416 | |||
417 | static void w90p910_enable_tx(struct net_device *dev, unsigned int enable) | ||
418 | { | ||
419 | struct w90p910_ether *ether = netdev_priv(dev); | ||
420 | unsigned int val; | ||
421 | |||
422 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
423 | |||
424 | if (enable) | ||
425 | val |= MCMDR_TXON; | ||
426 | else | ||
427 | val &= ~MCMDR_TXON; | ||
428 | |||
429 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
430 | } | ||
431 | |||
432 | static void w90p910_enable_rx(struct net_device *dev, unsigned int enable) | ||
433 | { | ||
434 | struct w90p910_ether *ether = netdev_priv(dev); | ||
435 | unsigned int val; | ||
436 | |||
437 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
438 | |||
439 | if (enable) | ||
440 | val |= MCMDR_RXON; | ||
441 | else | ||
442 | val &= ~MCMDR_RXON; | ||
443 | |||
444 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
445 | } | ||
446 | |||
447 | static void w90p910_set_curdest(struct net_device *dev) | ||
448 | { | ||
449 | struct w90p910_ether *ether = netdev_priv(dev); | ||
450 | |||
451 | __raw_writel(ether->start_rx_ptr, ether->reg + REG_RXDLSA); | ||
452 | __raw_writel(ether->start_tx_ptr, ether->reg + REG_TXDLSA); | ||
453 | } | ||
454 | |||
455 | static void w90p910_reset_mac(struct net_device *dev) | ||
456 | { | ||
457 | struct w90p910_ether *ether = netdev_priv(dev); | ||
458 | |||
459 | spin_lock(ðer->lock); | ||
460 | |||
461 | w90p910_enable_tx(dev, 0); | ||
462 | w90p910_enable_rx(dev, 0); | ||
463 | w90p910_set_fifo_threshold(dev); | ||
464 | w90p910_return_default_idle(dev); | ||
465 | |||
466 | if (!netif_queue_stopped(dev)) | ||
467 | netif_stop_queue(dev); | ||
468 | |||
469 | w90p910_init_desc(dev); | ||
470 | |||
471 | dev->trans_start = jiffies; | ||
472 | ether->cur_tx = 0x0; | ||
473 | ether->finish_tx = 0x0; | ||
474 | ether->cur_rx = 0x0; | ||
475 | |||
476 | w90p910_set_curdest(dev); | ||
477 | w90p910_enable_cam(dev); | ||
478 | w90p910_enable_cam_command(dev); | ||
479 | w90p910_enable_mac_interrupt(dev); | ||
480 | w90p910_enable_tx(dev, 1); | ||
481 | w90p910_enable_rx(dev, 1); | ||
482 | w90p910_trigger_tx(dev); | ||
483 | w90p910_trigger_rx(dev); | ||
484 | |||
485 | dev->trans_start = jiffies; | ||
486 | |||
487 | if (netif_queue_stopped(dev)) | ||
488 | netif_wake_queue(dev); | ||
489 | |||
490 | spin_unlock(ðer->lock); | ||
491 | } | ||
492 | |||
493 | static void w90p910_mdio_write(struct net_device *dev, | ||
494 | int phy_id, int reg, int data) | ||
495 | { | ||
496 | struct w90p910_ether *ether = netdev_priv(dev); | ||
497 | struct platform_device *pdev; | ||
498 | unsigned int val, i; | ||
499 | |||
500 | pdev = ether->pdev; | ||
501 | |||
502 | __raw_writel(data, ether->reg + REG_MIID); | ||
503 | |||
504 | val = (phy_id << 0x08) | reg; | ||
505 | val |= PHYBUSY | PHYWR | MDCCR_VAL; | ||
506 | __raw_writel(val, ether->reg + REG_MIIDA); | ||
507 | |||
508 | for (i = 0; i < DELAY; i++) { | ||
509 | if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0) | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | if (i == DELAY) | ||
514 | dev_warn(&pdev->dev, "mdio write timed out\n"); | ||
515 | } | ||
516 | |||
517 | static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg) | ||
518 | { | ||
519 | struct w90p910_ether *ether = netdev_priv(dev); | ||
520 | struct platform_device *pdev; | ||
521 | unsigned int val, i, data; | ||
522 | |||
523 | pdev = ether->pdev; | ||
524 | |||
525 | val = (phy_id << 0x08) | reg; | ||
526 | val |= PHYBUSY | MDCCR_VAL; | ||
527 | __raw_writel(val, ether->reg + REG_MIIDA); | ||
528 | |||
529 | for (i = 0; i < DELAY; i++) { | ||
530 | if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0) | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | if (i == DELAY) { | ||
535 | dev_warn(&pdev->dev, "mdio read timed out\n"); | ||
536 | data = 0xffff; | ||
537 | } else { | ||
538 | data = __raw_readl(ether->reg + REG_MIID); | ||
539 | } | ||
540 | |||
541 | return data; | ||
542 | } | ||
543 | |||
544 | static int set_mac_address(struct net_device *dev, void *addr) | ||
545 | { | ||
546 | struct sockaddr *address = addr; | ||
547 | |||
548 | if (!is_valid_ether_addr(address->sa_data)) | ||
549 | return -EADDRNOTAVAIL; | ||
550 | |||
551 | memcpy(dev->dev_addr, address->sa_data, dev->addr_len); | ||
552 | w90p910_write_cam(dev, CAM0, dev->dev_addr); | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | static int w90p910_ether_close(struct net_device *dev) | ||
558 | { | ||
559 | struct w90p910_ether *ether = netdev_priv(dev); | ||
560 | |||
561 | dma_free_writecombine(NULL, sizeof(struct w90p910_rxbd), | ||
562 | ether->rdesc, (dma_addr_t)ether->rdesc_phys); | ||
563 | dma_free_writecombine(NULL, sizeof(struct w90p910_txbd), | ||
564 | ether->tdesc, (dma_addr_t)ether->tdesc_phys); | ||
565 | |||
566 | netif_stop_queue(dev); | ||
567 | |||
568 | del_timer_sync(ðer->check_timer); | ||
569 | clk_disable(ether->rmiiclk); | ||
570 | clk_disable(ether->clk); | ||
571 | |||
572 | free_irq(ether->txirq, dev); | ||
573 | free_irq(ether->rxirq, dev); | ||
574 | |||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | static struct net_device_stats *w90p910_ether_stats(struct net_device *dev) | ||
579 | { | ||
580 | struct w90p910_ether *ether; | ||
581 | |||
582 | ether = netdev_priv(dev); | ||
583 | |||
584 | return ðer->stats; | ||
585 | } | ||
586 | |||
587 | static int w90p910_send_frame(struct net_device *dev, | ||
588 | unsigned char *data, int length) | ||
589 | { | ||
590 | struct w90p910_ether *ether; | ||
591 | struct w90p910_txbd *txbd; | ||
592 | struct platform_device *pdev; | ||
593 | unsigned char *buffer; | ||
594 | |||
595 | ether = netdev_priv(dev); | ||
596 | pdev = ether->pdev; | ||
597 | |||
598 | txbd = ðer->tdesc->desclist[ether->cur_tx]; | ||
599 | buffer = ether->tdesc->tran_buf[ether->cur_tx]; | ||
600 | if (length > 1514) { | ||
601 | dev_err(&pdev->dev, "send data %d bytes, check it\n", length); | ||
602 | length = 1514; | ||
603 | } | ||
604 | |||
605 | txbd->sl = length & 0xFFFF; | ||
606 | |||
607 | memcpy(buffer, data, length); | ||
608 | |||
609 | txbd->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE | MACTXINTEN; | ||
610 | |||
611 | w90p910_enable_tx(dev, 1); | ||
612 | |||
613 | w90p910_trigger_tx(dev); | ||
614 | |||
615 | ether->cur_tx = (ether->cur_tx+1) % TX_DESC_SIZE; | ||
616 | txbd = ðer->tdesc->desclist[ether->cur_tx]; | ||
617 | |||
618 | dev->trans_start = jiffies; | ||
619 | |||
620 | if (txbd->mode & TX_OWEN_DMA) | ||
621 | netif_stop_queue(dev); | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
627 | { | ||
628 | struct w90p910_ether *ether = netdev_priv(dev); | ||
629 | |||
630 | if (!(w90p910_send_frame(dev, skb->data, skb->len))) { | ||
631 | ether->skb = skb; | ||
632 | dev_kfree_skb_irq(skb); | ||
633 | return 0; | ||
634 | } | ||
635 | return -1; | ||
636 | } | ||
637 | |||
638 | static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id) | ||
639 | { | ||
640 | struct w90p910_ether *ether; | ||
641 | struct w90p910_txbd *txbd; | ||
642 | struct platform_device *pdev; | ||
643 | struct tran_pdesc *tran_pdesc; | ||
644 | struct net_device *dev; | ||
645 | unsigned int cur_entry, entry, status; | ||
646 | |||
647 | dev = (struct net_device *)dev_id; | ||
648 | ether = netdev_priv(dev); | ||
649 | pdev = ether->pdev; | ||
650 | |||
651 | spin_lock(ðer->lock); | ||
652 | |||
653 | w90p910_get_and_clear_int(dev, &status); | ||
654 | |||
655 | cur_entry = __raw_readl(ether->reg + REG_CTXDSA); | ||
656 | |||
657 | tran_pdesc = ether->tdesc_phys; | ||
658 | entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]); | ||
659 | |||
660 | while (entry != cur_entry) { | ||
661 | txbd = ðer->tdesc->desclist[ether->finish_tx]; | ||
662 | |||
663 | ether->finish_tx = (ether->finish_tx + 1) % TX_DESC_SIZE; | ||
664 | |||
665 | if (txbd->sl & TXDS_TXCP) { | ||
666 | ether->stats.tx_packets++; | ||
667 | ether->stats.tx_bytes += txbd->sl & 0xFFFF; | ||
668 | } else { | ||
669 | ether->stats.tx_errors++; | ||
670 | } | ||
671 | |||
672 | txbd->sl = 0x0; | ||
673 | txbd->mode = 0x0; | ||
674 | |||
675 | if (netif_queue_stopped(dev)) | ||
676 | netif_wake_queue(dev); | ||
677 | |||
678 | entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]); | ||
679 | } | ||
680 | |||
681 | if (status & MISTA_EXDEF) { | ||
682 | dev_err(&pdev->dev, "emc defer exceed interrupt\n"); | ||
683 | } else if (status & MISTA_TXBERR) { | ||
684 | dev_err(&pdev->dev, "emc bus error interrupt\n"); | ||
685 | w90p910_reset_mac(dev); | ||
686 | } else if (status & MISTA_TDU) { | ||
687 | if (netif_queue_stopped(dev)) | ||
688 | netif_wake_queue(dev); | ||
689 | } | ||
690 | |||
691 | spin_unlock(ðer->lock); | ||
692 | |||
693 | return IRQ_HANDLED; | ||
694 | } | ||
695 | |||
696 | static void netdev_rx(struct net_device *dev) | ||
697 | { | ||
698 | struct w90p910_ether *ether; | ||
699 | struct w90p910_rxbd *rxbd; | ||
700 | struct platform_device *pdev; | ||
701 | struct recv_pdesc *rdesc_phys; | ||
702 | struct sk_buff *skb; | ||
703 | unsigned char *data; | ||
704 | unsigned int length, status, val, entry; | ||
705 | |||
706 | ether = netdev_priv(dev); | ||
707 | pdev = ether->pdev; | ||
708 | rdesc_phys = ether->rdesc_phys; | ||
709 | |||
710 | rxbd = ðer->rdesc->desclist[ether->cur_rx]; | ||
711 | |||
712 | do { | ||
713 | val = __raw_readl(ether->reg + REG_CRXDSA); | ||
714 | entry = (unsigned int)&rdesc_phys->desclist[ether->cur_rx]; | ||
715 | |||
716 | if (val == entry) | ||
717 | break; | ||
718 | |||
719 | status = rxbd->sl; | ||
720 | length = status & 0xFFFF; | ||
721 | |||
722 | if (status & RXDS_RXGD) { | ||
723 | data = ether->rdesc->recv_buf[ether->cur_rx]; | ||
724 | skb = dev_alloc_skb(length+2); | ||
725 | if (!skb) { | ||
726 | dev_err(&pdev->dev, "get skb buffer error\n"); | ||
727 | ether->stats.rx_dropped++; | ||
728 | return; | ||
729 | } | ||
730 | |||
731 | skb->dev = dev; | ||
732 | skb_reserve(skb, 2); | ||
733 | skb_put(skb, length); | ||
734 | skb_copy_to_linear_data(skb, data, length); | ||
735 | skb->protocol = eth_type_trans(skb, dev); | ||
736 | ether->stats.rx_packets++; | ||
737 | ether->stats.rx_bytes += length; | ||
738 | netif_rx(skb); | ||
739 | } else { | ||
740 | ether->stats.rx_errors++; | ||
741 | |||
742 | if (status & RXDS_RP) { | ||
743 | dev_err(&pdev->dev, "rx runt err\n"); | ||
744 | ether->stats.rx_length_errors++; | ||
745 | } else if (status & RXDS_CRCE) { | ||
746 | dev_err(&pdev->dev, "rx crc err\n"); | ||
747 | ether->stats.rx_crc_errors++; | ||
748 | } | ||
749 | |||
750 | if (status & RXDS_ALIE) { | ||
751 | dev_err(&pdev->dev, "rx aligment err\n"); | ||
752 | ether->stats.rx_frame_errors++; | ||
753 | } else if (status & RXDS_PTLE) { | ||
754 | dev_err(&pdev->dev, "rx longer err\n"); | ||
755 | ether->stats.rx_over_errors++; | ||
756 | } | ||
757 | } | ||
758 | |||
759 | rxbd->sl = RX_OWEN_DMA; | ||
760 | rxbd->reserved = 0x0; | ||
761 | ether->cur_rx = (ether->cur_rx+1) % RX_DESC_SIZE; | ||
762 | rxbd = ðer->rdesc->desclist[ether->cur_rx]; | ||
763 | |||
764 | dev->last_rx = jiffies; | ||
765 | } while (1); | ||
766 | } | ||
767 | |||
768 | static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id) | ||
769 | { | ||
770 | struct net_device *dev; | ||
771 | struct w90p910_ether *ether; | ||
772 | struct platform_device *pdev; | ||
773 | unsigned int status; | ||
774 | |||
775 | dev = (struct net_device *)dev_id; | ||
776 | ether = netdev_priv(dev); | ||
777 | pdev = ether->pdev; | ||
778 | |||
779 | spin_lock(ðer->lock); | ||
780 | |||
781 | w90p910_get_and_clear_int(dev, &status); | ||
782 | |||
783 | if (status & MISTA_RDU) { | ||
784 | netdev_rx(dev); | ||
785 | |||
786 | w90p910_trigger_rx(dev); | ||
787 | |||
788 | spin_unlock(ðer->lock); | ||
789 | return IRQ_HANDLED; | ||
790 | } else if (status & MISTA_RXBERR) { | ||
791 | dev_err(&pdev->dev, "emc rx bus error\n"); | ||
792 | w90p910_reset_mac(dev); | ||
793 | } | ||
794 | |||
795 | netdev_rx(dev); | ||
796 | spin_unlock(ðer->lock); | ||
797 | return IRQ_HANDLED; | ||
798 | } | ||
799 | |||
800 | static int w90p910_ether_open(struct net_device *dev) | ||
801 | { | ||
802 | struct w90p910_ether *ether; | ||
803 | struct platform_device *pdev; | ||
804 | |||
805 | ether = netdev_priv(dev); | ||
806 | pdev = ether->pdev; | ||
807 | |||
808 | w90p910_reset_mac(dev); | ||
809 | w90p910_set_fifo_threshold(dev); | ||
810 | w90p910_set_curdest(dev); | ||
811 | w90p910_enable_cam(dev); | ||
812 | w90p910_enable_cam_command(dev); | ||
813 | w90p910_enable_mac_interrupt(dev); | ||
814 | w90p910_set_global_maccmd(dev); | ||
815 | w90p910_enable_rx(dev, 1); | ||
816 | |||
817 | ether->rx_packets = 0x0; | ||
818 | ether->rx_bytes = 0x0; | ||
819 | |||
820 | if (request_irq(ether->txirq, w90p910_tx_interrupt, | ||
821 | 0x0, pdev->name, dev)) { | ||
822 | dev_err(&pdev->dev, "register irq tx failed\n"); | ||
823 | return -EAGAIN; | ||
824 | } | ||
825 | |||
826 | if (request_irq(ether->rxirq, w90p910_rx_interrupt, | ||
827 | 0x0, pdev->name, dev)) { | ||
828 | dev_err(&pdev->dev, "register irq rx failed\n"); | ||
829 | return -EAGAIN; | ||
830 | } | ||
831 | |||
832 | mod_timer(ðer->check_timer, jiffies + msecs_to_jiffies(1000)); | ||
833 | netif_start_queue(dev); | ||
834 | w90p910_trigger_rx(dev); | ||
835 | |||
836 | dev_info(&pdev->dev, "%s is OPENED\n", dev->name); | ||
837 | |||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | static void w90p910_ether_set_multicast_list(struct net_device *dev) | ||
842 | { | ||
843 | struct w90p910_ether *ether; | ||
844 | unsigned int rx_mode; | ||
845 | |||
846 | ether = netdev_priv(dev); | ||
847 | |||
848 | if (dev->flags & IFF_PROMISC) | ||
849 | rx_mode = CAMCMR_AUP | CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP; | ||
850 | else if ((dev->flags & IFF_ALLMULTI) || dev->mc_list) | ||
851 | rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP; | ||
852 | else | ||
853 | rx_mode = CAMCMR_ECMP | CAMCMR_ABP; | ||
854 | __raw_writel(rx_mode, ether->reg + REG_CAMCMR); | ||
855 | } | ||
856 | |||
857 | static int w90p910_ether_ioctl(struct net_device *dev, | ||
858 | struct ifreq *ifr, int cmd) | ||
859 | { | ||
860 | struct w90p910_ether *ether = netdev_priv(dev); | ||
861 | struct mii_ioctl_data *data = if_mii(ifr); | ||
862 | |||
863 | return generic_mii_ioctl(ðer->mii, data, cmd, NULL); | ||
864 | } | ||
865 | |||
866 | static void w90p910_get_drvinfo(struct net_device *dev, | ||
867 | struct ethtool_drvinfo *info) | ||
868 | { | ||
869 | strcpy(info->driver, DRV_MODULE_NAME); | ||
870 | strcpy(info->version, DRV_MODULE_VERSION); | ||
871 | } | ||
872 | |||
873 | static int w90p910_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
874 | { | ||
875 | struct w90p910_ether *ether = netdev_priv(dev); | ||
876 | return mii_ethtool_gset(ðer->mii, cmd); | ||
877 | } | ||
878 | |||
879 | static int w90p910_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
880 | { | ||
881 | struct w90p910_ether *ether = netdev_priv(dev); | ||
882 | return mii_ethtool_sset(ðer->mii, cmd); | ||
883 | } | ||
884 | |||
885 | static int w90p910_nway_reset(struct net_device *dev) | ||
886 | { | ||
887 | struct w90p910_ether *ether = netdev_priv(dev); | ||
888 | return mii_nway_restart(ðer->mii); | ||
889 | } | ||
890 | |||
891 | static u32 w90p910_get_link(struct net_device *dev) | ||
892 | { | ||
893 | struct w90p910_ether *ether = netdev_priv(dev); | ||
894 | return mii_link_ok(ðer->mii); | ||
895 | } | ||
896 | |||
897 | static const struct ethtool_ops w90p910_ether_ethtool_ops = { | ||
898 | .get_settings = w90p910_get_settings, | ||
899 | .set_settings = w90p910_set_settings, | ||
900 | .get_drvinfo = w90p910_get_drvinfo, | ||
901 | .nway_reset = w90p910_nway_reset, | ||
902 | .get_link = w90p910_get_link, | ||
903 | }; | ||
904 | |||
905 | static const struct net_device_ops w90p910_ether_netdev_ops = { | ||
906 | .ndo_open = w90p910_ether_open, | ||
907 | .ndo_stop = w90p910_ether_close, | ||
908 | .ndo_start_xmit = w90p910_ether_start_xmit, | ||
909 | .ndo_get_stats = w90p910_ether_stats, | ||
910 | .ndo_set_multicast_list = w90p910_ether_set_multicast_list, | ||
911 | .ndo_set_mac_address = set_mac_address, | ||
912 | .ndo_do_ioctl = w90p910_ether_ioctl, | ||
913 | .ndo_validate_addr = eth_validate_addr, | ||
914 | .ndo_change_mtu = eth_change_mtu, | ||
915 | }; | ||
916 | |||
917 | static void __init get_mac_address(struct net_device *dev) | ||
918 | { | ||
919 | struct w90p910_ether *ether = netdev_priv(dev); | ||
920 | struct platform_device *pdev; | ||
921 | char addr[6]; | ||
922 | |||
923 | pdev = ether->pdev; | ||
924 | |||
925 | addr[0] = 0x00; | ||
926 | addr[1] = 0x02; | ||
927 | addr[2] = 0xac; | ||
928 | addr[3] = 0x55; | ||
929 | addr[4] = 0x88; | ||
930 | addr[5] = 0xa8; | ||
931 | |||
932 | if (is_valid_ether_addr(addr)) | ||
933 | memcpy(dev->dev_addr, &addr, 0x06); | ||
934 | else | ||
935 | dev_err(&pdev->dev, "invalid mac address\n"); | ||
936 | } | ||
937 | |||
938 | static int w90p910_ether_setup(struct net_device *dev) | ||
939 | { | ||
940 | struct w90p910_ether *ether = netdev_priv(dev); | ||
941 | |||
942 | ether_setup(dev); | ||
943 | dev->netdev_ops = &w90p910_ether_netdev_ops; | ||
944 | dev->ethtool_ops = &w90p910_ether_ethtool_ops; | ||
945 | |||
946 | dev->tx_queue_len = 16; | ||
947 | dev->dma = 0x0; | ||
948 | dev->watchdog_timeo = TX_TIMEOUT; | ||
949 | |||
950 | get_mac_address(dev); | ||
951 | |||
952 | spin_lock_init(ðer->lock); | ||
953 | |||
954 | ether->cur_tx = 0x0; | ||
955 | ether->cur_rx = 0x0; | ||
956 | ether->finish_tx = 0x0; | ||
957 | ether->linkflag = 0x0; | ||
958 | ether->mii.phy_id = 0x01; | ||
959 | ether->mii.phy_id_mask = 0x1f; | ||
960 | ether->mii.reg_num_mask = 0x1f; | ||
961 | ether->mii.dev = dev; | ||
962 | ether->mii.mdio_read = w90p910_mdio_read; | ||
963 | ether->mii.mdio_write = w90p910_mdio_write; | ||
964 | |||
965 | setup_timer(ðer->check_timer, w90p910_check_link, | ||
966 | (unsigned long)dev); | ||
967 | |||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | static int __devinit w90p910_ether_probe(struct platform_device *pdev) | ||
972 | { | ||
973 | struct w90p910_ether *ether; | ||
974 | struct net_device *dev; | ||
975 | struct resource *res; | ||
976 | int error; | ||
977 | |||
978 | dev = alloc_etherdev(sizeof(struct w90p910_ether)); | ||
979 | if (!dev) | ||
980 | return -ENOMEM; | ||
981 | |||
982 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
983 | if (res == NULL) { | ||
984 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
985 | error = -ENXIO; | ||
986 | goto failed_free; | ||
987 | } | ||
988 | |||
989 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
990 | if (res == NULL) { | ||
991 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
992 | error = -EBUSY; | ||
993 | goto failed_free; | ||
994 | } | ||
995 | |||
996 | ether = netdev_priv(dev); | ||
997 | |||
998 | ether->reg = ioremap(res->start, resource_size(res)); | ||
999 | if (ether->reg == NULL) { | ||
1000 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
1001 | error = -ENXIO; | ||
1002 | goto failed_free_mem; | ||
1003 | } | ||
1004 | |||
1005 | ether->txirq = platform_get_irq(pdev, 0); | ||
1006 | if (ether->txirq < 0) { | ||
1007 | dev_err(&pdev->dev, "failed to get ether tx irq\n"); | ||
1008 | error = -ENXIO; | ||
1009 | goto failed_free_io; | ||
1010 | } | ||
1011 | |||
1012 | ether->rxirq = platform_get_irq(pdev, 1); | ||
1013 | if (ether->rxirq < 0) { | ||
1014 | dev_err(&pdev->dev, "failed to get ether rx irq\n"); | ||
1015 | error = -ENXIO; | ||
1016 | goto failed_free_txirq; | ||
1017 | } | ||
1018 | |||
1019 | platform_set_drvdata(pdev, dev); | ||
1020 | |||
1021 | ether->clk = clk_get(&pdev->dev, NULL); | ||
1022 | if (IS_ERR(ether->clk)) { | ||
1023 | dev_err(&pdev->dev, "failed to get ether clock\n"); | ||
1024 | error = PTR_ERR(ether->clk); | ||
1025 | goto failed_free_rxirq; | ||
1026 | } | ||
1027 | |||
1028 | ether->rmiiclk = clk_get(&pdev->dev, "RMII"); | ||
1029 | if (IS_ERR(ether->rmiiclk)) { | ||
1030 | dev_err(&pdev->dev, "failed to get ether clock\n"); | ||
1031 | error = PTR_ERR(ether->rmiiclk); | ||
1032 | goto failed_put_clk; | ||
1033 | } | ||
1034 | |||
1035 | ether->pdev = pdev; | ||
1036 | |||
1037 | w90p910_ether_setup(dev); | ||
1038 | |||
1039 | error = register_netdev(dev); | ||
1040 | if (error != 0) { | ||
1041 | dev_err(&pdev->dev, "Regiter EMC w90p910 FAILED\n"); | ||
1042 | error = -ENODEV; | ||
1043 | goto failed_put_rmiiclk; | ||
1044 | } | ||
1045 | |||
1046 | return 0; | ||
1047 | failed_put_rmiiclk: | ||
1048 | clk_put(ether->rmiiclk); | ||
1049 | failed_put_clk: | ||
1050 | clk_put(ether->clk); | ||
1051 | failed_free_rxirq: | ||
1052 | free_irq(ether->rxirq, pdev); | ||
1053 | platform_set_drvdata(pdev, NULL); | ||
1054 | failed_free_txirq: | ||
1055 | free_irq(ether->txirq, pdev); | ||
1056 | failed_free_io: | ||
1057 | iounmap(ether->reg); | ||
1058 | failed_free_mem: | ||
1059 | release_mem_region(res->start, resource_size(res)); | ||
1060 | failed_free: | ||
1061 | free_netdev(dev); | ||
1062 | return error; | ||
1063 | } | ||
1064 | |||
1065 | static int __devexit w90p910_ether_remove(struct platform_device *pdev) | ||
1066 | { | ||
1067 | struct net_device *dev = platform_get_drvdata(pdev); | ||
1068 | struct w90p910_ether *ether = netdev_priv(dev); | ||
1069 | |||
1070 | unregister_netdev(dev); | ||
1071 | clk_put(ether->rmiiclk); | ||
1072 | clk_put(ether->clk); | ||
1073 | del_timer_sync(ðer->check_timer); | ||
1074 | platform_set_drvdata(pdev, NULL); | ||
1075 | free_netdev(dev); | ||
1076 | return 0; | ||
1077 | } | ||
1078 | |||
1079 | static struct platform_driver w90p910_ether_driver = { | ||
1080 | .probe = w90p910_ether_probe, | ||
1081 | .remove = __devexit_p(w90p910_ether_remove), | ||
1082 | .driver = { | ||
1083 | .name = "w90p910-emc", | ||
1084 | .owner = THIS_MODULE, | ||
1085 | }, | ||
1086 | }; | ||
1087 | |||
1088 | static int __init w90p910_ether_init(void) | ||
1089 | { | ||
1090 | return platform_driver_register(&w90p910_ether_driver); | ||
1091 | } | ||
1092 | |||
1093 | static void __exit w90p910_ether_exit(void) | ||
1094 | { | ||
1095 | platform_driver_unregister(&w90p910_ether_driver); | ||
1096 | } | ||
1097 | |||
1098 | module_init(w90p910_ether_init); | ||
1099 | module_exit(w90p910_ether_exit); | ||
1100 | |||
1101 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
1102 | MODULE_DESCRIPTION("w90p910 MAC driver!"); | ||
1103 | MODULE_LICENSE("GPL"); | ||
1104 | MODULE_ALIAS("platform:w90p910-emc"); | ||
1105 | |||
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index e1658ef3fcdf..2a1120ad2e74 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h | |||
@@ -188,14 +188,14 @@ struct atl1c_tpd_ext_desc { | |||
188 | #define RRS_HDS_TYPE_DATA 2 | 188 | #define RRS_HDS_TYPE_DATA 2 |
189 | 189 | ||
190 | #define RRS_IS_NO_HDS_TYPE(flag) \ | 190 | #define RRS_IS_NO_HDS_TYPE(flag) \ |
191 | (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == 0) | 191 | ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == 0) |
192 | 192 | ||
193 | #define RRS_IS_HDS_HEAD(flag) \ | 193 | #define RRS_IS_HDS_HEAD(flag) \ |
194 | (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \ | 194 | ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \ |
195 | RRS_HDS_TYPE_HEAD) | 195 | RRS_HDS_TYPE_HEAD) |
196 | 196 | ||
197 | #define RRS_IS_HDS_DATA(flag) \ | 197 | #define RRS_IS_HDS_DATA(flag) \ |
198 | (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \ | 198 | ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \ |
199 | RRS_HDS_TYPE_DATA) | 199 | RRS_HDS_TYPE_DATA) |
200 | 200 | ||
201 | /* rrs word 3 bit 0:31 */ | 201 | /* rrs word 3 bit 0:31 */ |
@@ -245,7 +245,7 @@ struct atl1c_tpd_ext_desc { | |||
245 | #define RRS_PACKET_TYPE_802_3 1 | 245 | #define RRS_PACKET_TYPE_802_3 1 |
246 | #define RRS_PACKET_TYPE_ETH 0 | 246 | #define RRS_PACKET_TYPE_ETH 0 |
247 | #define RRS_PACKET_IS_ETH(word) \ | 247 | #define RRS_PACKET_IS_ETH(word) \ |
248 | (((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK == \ | 248 | ((((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK) == \ |
249 | RRS_PACKET_TYPE_ETH) | 249 | RRS_PACKET_TYPE_ETH) |
250 | #define RRS_RXD_IS_VALID(word) \ | 250 | #define RRS_RXD_IS_VALID(word) \ |
251 | ((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1) | 251 | ((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1) |
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index cd547a205fb9..a383122679de 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c | |||
@@ -1689,7 +1689,7 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, | |||
1689 | if (likely(RRS_RXD_IS_VALID(rrs->word3))) { | 1689 | if (likely(RRS_RXD_IS_VALID(rrs->word3))) { |
1690 | rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) & | 1690 | rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) & |
1691 | RRS_RX_RFD_CNT_MASK; | 1691 | RRS_RX_RFD_CNT_MASK; |
1692 | if (unlikely(rfd_num) != 1) | 1692 | if (unlikely(rfd_num != 1)) |
1693 | /* TODO support mul rfd*/ | 1693 | /* TODO support mul rfd*/ |
1694 | if (netif_msg_rx_err(adapter)) | 1694 | if (netif_msg_rx_err(adapter)) |
1695 | dev_warn(&pdev->dev, | 1695 | dev_warn(&pdev->dev, |
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index ed648acef7cf..2ee581a2cdec 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c | |||
@@ -4212,13 +4212,14 @@ static void bnx2x_turn_off_sf(struct bnx2x *bp, u8 port) | |||
4212 | u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, | 4212 | u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, |
4213 | u8 *version, u16 len) | 4213 | u8 *version, u16 len) |
4214 | { | 4214 | { |
4215 | struct bnx2x *bp = params->bp; | 4215 | struct bnx2x *bp; |
4216 | u32 ext_phy_type = 0; | 4216 | u32 ext_phy_type = 0; |
4217 | u32 spirom_ver = 0; | 4217 | u32 spirom_ver = 0; |
4218 | u8 status = 0 ; | 4218 | u8 status = 0 ; |
4219 | 4219 | ||
4220 | if (version == NULL || params == NULL) | 4220 | if (version == NULL || params == NULL) |
4221 | return -EINVAL; | 4221 | return -EINVAL; |
4222 | bp = params->bp; | ||
4222 | 4223 | ||
4223 | spirom_ver = REG_RD(bp, params->shmem_base + | 4224 | spirom_ver = REG_RD(bp, params->shmem_base + |
4224 | offsetof(struct shmem_region, | 4225 | offsetof(struct shmem_region, |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d927f71af8a3..aa1be1feceed 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1459,8 +1459,16 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1459 | * ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond | 1459 | * ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond |
1460 | */ | 1460 | */ |
1461 | if (bond->slave_cnt == 0) { | 1461 | if (bond->slave_cnt == 0) { |
1462 | if (slave_dev->type != ARPHRD_ETHER) | 1462 | if (bond_dev->type != slave_dev->type) { |
1463 | bond_setup_by_slave(bond_dev, slave_dev); | 1463 | dev_close(bond_dev); |
1464 | pr_debug("%s: change device type from %d to %d\n", | ||
1465 | bond_dev->name, bond_dev->type, slave_dev->type); | ||
1466 | if (slave_dev->type != ARPHRD_ETHER) | ||
1467 | bond_setup_by_slave(bond_dev, slave_dev); | ||
1468 | else | ||
1469 | ether_setup(bond_dev); | ||
1470 | dev_open(bond_dev); | ||
1471 | } | ||
1464 | } else if (bond_dev->type != slave_dev->type) { | 1472 | } else if (bond_dev->type != slave_dev->type) { |
1465 | pr_err(DRV_NAME ": %s ether type (%d) is different " | 1473 | pr_err(DRV_NAME ": %s ether type (%d) is different " |
1466 | "from other slaves (%d), can not enslave it.\n", | 1474 | "from other slaves (%d), can not enslave it.\n", |
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 574daddc21bf..9e4283aff828 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c | |||
@@ -346,7 +346,7 @@ void can_restart(unsigned long data) | |||
346 | skb = dev_alloc_skb(sizeof(struct can_frame)); | 346 | skb = dev_alloc_skb(sizeof(struct can_frame)); |
347 | if (skb == NULL) { | 347 | if (skb == NULL) { |
348 | err = -ENOMEM; | 348 | err = -ENOMEM; |
349 | goto out; | 349 | goto restart; |
350 | } | 350 | } |
351 | skb->dev = dev; | 351 | skb->dev = dev; |
352 | skb->protocol = htons(ETH_P_CAN); | 352 | skb->protocol = htons(ETH_P_CAN); |
@@ -361,13 +361,13 @@ void can_restart(unsigned long data) | |||
361 | stats->rx_packets++; | 361 | stats->rx_packets++; |
362 | stats->rx_bytes += cf->can_dlc; | 362 | stats->rx_bytes += cf->can_dlc; |
363 | 363 | ||
364 | restart: | ||
364 | dev_dbg(dev->dev.parent, "restarted\n"); | 365 | dev_dbg(dev->dev.parent, "restarted\n"); |
365 | priv->can_stats.restarts++; | 366 | priv->can_stats.restarts++; |
366 | 367 | ||
367 | /* Now restart the device */ | 368 | /* Now restart the device */ |
368 | err = priv->do_set_mode(dev, CAN_MODE_START); | 369 | err = priv->do_set_mode(dev, CAN_MODE_START); |
369 | 370 | ||
370 | out: | ||
371 | netif_carrier_on(dev); | 371 | netif_carrier_on(dev); |
372 | if (err) | 372 | if (err) |
373 | dev_err(dev->dev.parent, "Error %d during restart", err); | 373 | dev_err(dev->dev.parent, "Error %d during restart", err); |
@@ -473,6 +473,10 @@ int open_candev(struct net_device *dev) | |||
473 | return -EINVAL; | 473 | return -EINVAL; |
474 | } | 474 | } |
475 | 475 | ||
476 | /* Switch carrier on if device was stopped while in bus-off state */ | ||
477 | if (!netif_carrier_ok(dev)) | ||
478 | netif_carrier_on(dev); | ||
479 | |||
476 | setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev); | 480 | setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev); |
477 | 481 | ||
478 | return 0; | 482 | return 0; |
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 571f133a8fec..08ebee79d8a6 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c | |||
@@ -63,7 +63,6 @@ | |||
63 | #include <linux/can.h> | 63 | #include <linux/can.h> |
64 | #include <linux/can/dev.h> | 64 | #include <linux/can/dev.h> |
65 | #include <linux/can/error.h> | 65 | #include <linux/can/error.h> |
66 | #include <linux/can/dev.h> | ||
67 | 66 | ||
68 | #include "sja1000.h" | 67 | #include "sja1000.h" |
69 | 68 | ||
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index efa680f4b8dd..41b648a67fec 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
@@ -1897,6 +1897,9 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1897 | 1897 | ||
1898 | if (ioread8(&nic->csr->scb.status) & rus_no_res) | 1898 | if (ioread8(&nic->csr->scb.status) & rus_no_res) |
1899 | nic->ru_running = RU_SUSPENDED; | 1899 | nic->ru_running = RU_SUSPENDED; |
1900 | pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, | ||
1901 | sizeof(struct rfd), | ||
1902 | PCI_DMA_BIDIRECTIONAL); | ||
1900 | return -ENODATA; | 1903 | return -ENODATA; |
1901 | } | 1904 | } |
1902 | 1905 | ||
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 155160052c8b..981ab530e9ac 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * devices like TTY. It interfaces between a raw TTY and the | 3 | * devices like TTY. It interfaces between a raw TTY and the |
4 | * kernel's AX.25 protocol layers. | 4 | * kernel's AX.25 protocol layers. |
5 | * | 5 | * |
6 | * Authors: Andreas Könsgen <ajk@iehk.rwth-aachen.de> | 6 | * Authors: Andreas Könsgen <ajk@comnets.uni-bremen.de> |
7 | * Ralf Baechle DL5RB <ralf@linux-mips.org> | 7 | * Ralf Baechle DL5RB <ralf@linux-mips.org> |
8 | * | 8 | * |
9 | * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by | 9 | * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by |
diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c index 1d5379de6900..8d76cb89dbd6 100644 --- a/drivers/net/ibm_newemac/rgmii.c +++ b/drivers/net/ibm_newemac/rgmii.c | |||
@@ -188,11 +188,12 @@ void rgmii_put_mdio(struct of_device *ofdev, int input) | |||
188 | void rgmii_detach(struct of_device *ofdev, int input) | 188 | void rgmii_detach(struct of_device *ofdev, int input) |
189 | { | 189 | { |
190 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 190 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
191 | struct rgmii_regs __iomem *p = dev->base; | 191 | struct rgmii_regs __iomem *p; |
192 | |||
193 | mutex_lock(&dev->lock); | ||
194 | 192 | ||
195 | BUG_ON(!dev || dev->users == 0); | 193 | BUG_ON(!dev || dev->users == 0); |
194 | p = dev->base; | ||
195 | |||
196 | mutex_lock(&dev->lock); | ||
196 | 197 | ||
197 | RGMII_DBG(dev, "detach(%d)" NL, input); | 198 | RGMII_DBG(dev, "detach(%d)" NL, input); |
198 | 199 | ||
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 7c5978ad929a..da2c8514b8d0 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c | |||
@@ -106,8 +106,6 @@ static u8 ixgbe_dcbnl_get_state(struct net_device *netdev) | |||
106 | { | 106 | { |
107 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 107 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
108 | 108 | ||
109 | DPRINTK(DRV, INFO, "Get DCB Admin Mode.\n"); | ||
110 | |||
111 | return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED); | 109 | return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED); |
112 | } | 110 | } |
113 | 111 | ||
@@ -116,8 +114,6 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | |||
116 | u8 err = 0; | 114 | u8 err = 0; |
117 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 115 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
118 | 116 | ||
119 | DPRINTK(DRV, INFO, "Set DCB Admin Mode.\n"); | ||
120 | |||
121 | if (state > 0) { | 117 | if (state > 0) { |
122 | /* Turn on DCB */ | 118 | /* Turn on DCB */ |
123 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) | 119 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) |
@@ -175,6 +171,8 @@ static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev, | |||
175 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 171 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
176 | int i, j; | 172 | int i, j; |
177 | 173 | ||
174 | memset(perm_addr, 0xff, MAX_ADDR_LEN); | ||
175 | |||
178 | for (i = 0; i < netdev->addr_len; i++) | 176 | for (i = 0; i < netdev->addr_len; i++) |
179 | perm_addr[i] = adapter->hw.mac.perm_addr[i]; | 177 | perm_addr[i] = adapter->hw.mac.perm_addr[i]; |
180 | 178 | ||
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index d12106b47bf2..2f286091394d 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c | |||
@@ -229,6 +229,7 @@ static int __init jazz_sonic_probe(struct platform_device *pdev) | |||
229 | lp = netdev_priv(dev); | 229 | lp = netdev_priv(dev); |
230 | lp->device = &pdev->dev; | 230 | lp->device = &pdev->dev; |
231 | SET_NETDEV_DEV(dev, &pdev->dev); | 231 | SET_NETDEV_DEV(dev, &pdev->dev); |
232 | platform_set_drvdata(pdev, dev); | ||
232 | 233 | ||
233 | netdev_boot_setup_check(dev); | 234 | netdev_boot_setup_check(dev); |
234 | 235 | ||
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c new file mode 100644 index 000000000000..9a1dea60c1c4 --- /dev/null +++ b/drivers/net/ks8851.c | |||
@@ -0,0 +1,1322 @@ | |||
1 | /* drivers/net/ks8651.c | ||
2 | * | ||
3 | * Copyright 2009 Simtec Electronics | ||
4 | * http://www.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #define DEBUG | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/netdevice.h> | ||
17 | #include <linux/etherdevice.h> | ||
18 | #include <linux/ethtool.h> | ||
19 | #include <linux/cache.h> | ||
20 | #include <linux/crc32.h> | ||
21 | #include <linux/mii.h> | ||
22 | |||
23 | #include <linux/spi/spi.h> | ||
24 | |||
25 | #include "ks8851.h" | ||
26 | |||
27 | /** | ||
28 | * struct ks8851_rxctrl - KS8851 driver rx control | ||
29 | * @mchash: Multicast hash-table data. | ||
30 | * @rxcr1: KS_RXCR1 register setting | ||
31 | * @rxcr2: KS_RXCR2 register setting | ||
32 | * | ||
33 | * Representation of the settings needs to control the receive filtering | ||
34 | * such as the multicast hash-filter and the receive register settings. This | ||
35 | * is used to make the job of working out if the receive settings change and | ||
36 | * then issuing the new settings to the worker that will send the necessary | ||
37 | * commands. | ||
38 | */ | ||
39 | struct ks8851_rxctrl { | ||
40 | u16 mchash[4]; | ||
41 | u16 rxcr1; | ||
42 | u16 rxcr2; | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * union ks8851_tx_hdr - tx header data | ||
47 | * @txb: The header as bytes | ||
48 | * @txw: The header as 16bit, little-endian words | ||
49 | * | ||
50 | * A dual representation of the tx header data to allow | ||
51 | * access to individual bytes, and to allow 16bit accesses | ||
52 | * with 16bit alignment. | ||
53 | */ | ||
54 | union ks8851_tx_hdr { | ||
55 | u8 txb[6]; | ||
56 | __le16 txw[3]; | ||
57 | }; | ||
58 | |||
59 | /** | ||
60 | * struct ks8851_net - KS8851 driver private data | ||
61 | * @netdev: The network device we're bound to | ||
62 | * @spidev: The spi device we're bound to. | ||
63 | * @lock: Lock to ensure that the device is not accessed when busy. | ||
64 | * @statelock: Lock on this structure for tx list. | ||
65 | * @mii: The MII state information for the mii calls. | ||
66 | * @rxctrl: RX settings for @rxctrl_work. | ||
67 | * @tx_work: Work queue for tx packets | ||
68 | * @irq_work: Work queue for servicing interrupts | ||
69 | * @rxctrl_work: Work queue for updating RX mode and multicast lists | ||
70 | * @txq: Queue of packets for transmission. | ||
71 | * @spi_msg1: pre-setup SPI transfer with one message, @spi_xfer1. | ||
72 | * @spi_msg2: pre-setup SPI transfer with two messages, @spi_xfer2. | ||
73 | * @txh: Space for generating packet TX header in DMA-able data | ||
74 | * @rxd: Space for receiving SPI data, in DMA-able space. | ||
75 | * @txd: Space for transmitting SPI data, in DMA-able space. | ||
76 | * @msg_enable: The message flags controlling driver output (see ethtool). | ||
77 | * @fid: Incrementing frame id tag. | ||
78 | * @rc_ier: Cached copy of KS_IER. | ||
79 | * @rc_rxqcr: Cached copy of KS_RXQCR. | ||
80 | * | ||
81 | * The @lock ensures that the chip is protected when certain operations are | ||
82 | * in progress. When the read or write packet transfer is in progress, most | ||
83 | * of the chip registers are not ccessible until the transfer is finished and | ||
84 | * the DMA has been de-asserted. | ||
85 | * | ||
86 | * The @statelock is used to protect information in the structure which may | ||
87 | * need to be accessed via several sources, such as the network driver layer | ||
88 | * or one of the work queues. | ||
89 | * | ||
90 | * We align the buffers we may use for rx/tx to ensure that if the SPI driver | ||
91 | * wants to DMA map them, it will not have any problems with data the driver | ||
92 | * modifies. | ||
93 | */ | ||
94 | struct ks8851_net { | ||
95 | struct net_device *netdev; | ||
96 | struct spi_device *spidev; | ||
97 | struct mutex lock; | ||
98 | spinlock_t statelock; | ||
99 | |||
100 | union ks8851_tx_hdr txh ____cacheline_aligned; | ||
101 | u8 rxd[8]; | ||
102 | u8 txd[8]; | ||
103 | |||
104 | u32 msg_enable ____cacheline_aligned; | ||
105 | u16 tx_space; | ||
106 | u8 fid; | ||
107 | |||
108 | u16 rc_ier; | ||
109 | u16 rc_rxqcr; | ||
110 | |||
111 | struct mii_if_info mii; | ||
112 | struct ks8851_rxctrl rxctrl; | ||
113 | |||
114 | struct work_struct tx_work; | ||
115 | struct work_struct irq_work; | ||
116 | struct work_struct rxctrl_work; | ||
117 | |||
118 | struct sk_buff_head txq; | ||
119 | |||
120 | struct spi_message spi_msg1; | ||
121 | struct spi_message spi_msg2; | ||
122 | struct spi_transfer spi_xfer1; | ||
123 | struct spi_transfer spi_xfer2[2]; | ||
124 | }; | ||
125 | |||
126 | static int msg_enable; | ||
127 | |||
128 | #define ks_info(_ks, _msg...) dev_info(&(_ks)->spidev->dev, _msg) | ||
129 | #define ks_warn(_ks, _msg...) dev_warn(&(_ks)->spidev->dev, _msg) | ||
130 | #define ks_dbg(_ks, _msg...) dev_dbg(&(_ks)->spidev->dev, _msg) | ||
131 | #define ks_err(_ks, _msg...) dev_err(&(_ks)->spidev->dev, _msg) | ||
132 | |||
133 | /* shift for byte-enable data */ | ||
134 | #define BYTE_EN(_x) ((_x) << 2) | ||
135 | |||
136 | /* turn register number and byte-enable mask into data for start of packet */ | ||
137 | #define MK_OP(_byteen, _reg) (BYTE_EN(_byteen) | (_reg) << (8+2) | (_reg) >> 6) | ||
138 | |||
139 | /* SPI register read/write calls. | ||
140 | * | ||
141 | * All these calls issue SPI transactions to access the chip's registers. They | ||
142 | * all require that the necessary lock is held to prevent accesses when the | ||
143 | * chip is busy transfering packet data (RX/TX FIFO accesses). | ||
144 | */ | ||
145 | |||
146 | /** | ||
147 | * ks8851_wrreg16 - write 16bit register value to chip | ||
148 | * @ks: The chip state | ||
149 | * @reg: The register address | ||
150 | * @val: The value to write | ||
151 | * | ||
152 | * Issue a write to put the value @val into the register specified in @reg. | ||
153 | */ | ||
154 | static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val) | ||
155 | { | ||
156 | struct spi_transfer *xfer = &ks->spi_xfer1; | ||
157 | struct spi_message *msg = &ks->spi_msg1; | ||
158 | __le16 txb[2]; | ||
159 | int ret; | ||
160 | |||
161 | txb[0] = cpu_to_le16(MK_OP(reg & 2 ? 0xC : 0x03, reg) | KS_SPIOP_WR); | ||
162 | txb[1] = cpu_to_le16(val); | ||
163 | |||
164 | xfer->tx_buf = txb; | ||
165 | xfer->rx_buf = NULL; | ||
166 | xfer->len = 4; | ||
167 | |||
168 | ret = spi_sync(ks->spidev, msg); | ||
169 | if (ret < 0) | ||
170 | ks_err(ks, "spi_sync() failed\n"); | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * ks8851_rx_1msg - select whether to use one or two messages for spi read | ||
175 | * @ks: The device structure | ||
176 | * | ||
177 | * Return whether to generate a single message with a tx and rx buffer | ||
178 | * supplied to spi_sync(), or alternatively send the tx and rx buffers | ||
179 | * as separate messages. | ||
180 | * | ||
181 | * Depending on the hardware in use, a single message may be more efficient | ||
182 | * on interrupts or work done by the driver. | ||
183 | * | ||
184 | * This currently always returns true until we add some per-device data passed | ||
185 | * from the platform code to specify which mode is better. | ||
186 | */ | ||
187 | static inline bool ks8851_rx_1msg(struct ks8851_net *ks) | ||
188 | { | ||
189 | return true; | ||
190 | } | ||
191 | |||
192 | /** | ||
193 | * ks8851_rdreg - issue read register command and return the data | ||
194 | * @ks: The device state | ||
195 | * @op: The register address and byte enables in message format. | ||
196 | * @rxb: The RX buffer to return the result into | ||
197 | * @rxl: The length of data expected. | ||
198 | * | ||
199 | * This is the low level read call that issues the necessary spi message(s) | ||
200 | * to read data from the register specified in @op. | ||
201 | */ | ||
202 | static void ks8851_rdreg(struct ks8851_net *ks, unsigned op, | ||
203 | u8 *rxb, unsigned rxl) | ||
204 | { | ||
205 | struct spi_transfer *xfer; | ||
206 | struct spi_message *msg; | ||
207 | __le16 *txb = (__le16 *)ks->txd; | ||
208 | u8 *trx = ks->rxd; | ||
209 | int ret; | ||
210 | |||
211 | txb[0] = cpu_to_le16(op | KS_SPIOP_RD); | ||
212 | |||
213 | if (ks8851_rx_1msg(ks)) { | ||
214 | msg = &ks->spi_msg1; | ||
215 | xfer = &ks->spi_xfer1; | ||
216 | |||
217 | xfer->tx_buf = txb; | ||
218 | xfer->rx_buf = trx; | ||
219 | xfer->len = rxl + 2; | ||
220 | } else { | ||
221 | msg = &ks->spi_msg2; | ||
222 | xfer = ks->spi_xfer2; | ||
223 | |||
224 | xfer->tx_buf = txb; | ||
225 | xfer->rx_buf = NULL; | ||
226 | xfer->len = 2; | ||
227 | |||
228 | xfer++; | ||
229 | xfer->tx_buf = NULL; | ||
230 | xfer->rx_buf = trx; | ||
231 | xfer->len = rxl; | ||
232 | } | ||
233 | |||
234 | ret = spi_sync(ks->spidev, msg); | ||
235 | if (ret < 0) | ||
236 | ks_err(ks, "read: spi_sync() failed\n"); | ||
237 | else if (ks8851_rx_1msg(ks)) | ||
238 | memcpy(rxb, trx + 2, rxl); | ||
239 | else | ||
240 | memcpy(rxb, trx, rxl); | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | * ks8851_rdreg8 - read 8 bit register from device | ||
245 | * @ks: The chip information | ||
246 | * @reg: The register address | ||
247 | * | ||
248 | * Read a 8bit register from the chip, returning the result | ||
249 | */ | ||
250 | static unsigned ks8851_rdreg8(struct ks8851_net *ks, unsigned reg) | ||
251 | { | ||
252 | u8 rxb[1]; | ||
253 | |||
254 | ks8851_rdreg(ks, MK_OP(1 << (reg & 3), reg), rxb, 1); | ||
255 | return rxb[0]; | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * ks8851_rdreg16 - read 16 bit register from device | ||
260 | * @ks: The chip information | ||
261 | * @reg: The register address | ||
262 | * | ||
263 | * Read a 16bit register from the chip, returning the result | ||
264 | */ | ||
265 | static unsigned ks8851_rdreg16(struct ks8851_net *ks, unsigned reg) | ||
266 | { | ||
267 | __le16 rx = 0; | ||
268 | |||
269 | ks8851_rdreg(ks, MK_OP(reg & 2 ? 0xC : 0x3, reg), (u8 *)&rx, 2); | ||
270 | return le16_to_cpu(rx); | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * ks8851_rdreg32 - read 32 bit register from device | ||
275 | * @ks: The chip information | ||
276 | * @reg: The register address | ||
277 | * | ||
278 | * Read a 32bit register from the chip. | ||
279 | * | ||
280 | * Note, this read requires the address be aligned to 4 bytes. | ||
281 | */ | ||
282 | static unsigned ks8851_rdreg32(struct ks8851_net *ks, unsigned reg) | ||
283 | { | ||
284 | __le32 rx = 0; | ||
285 | |||
286 | WARN_ON(reg & 3); | ||
287 | |||
288 | ks8851_rdreg(ks, MK_OP(0xf, reg), (u8 *)&rx, 4); | ||
289 | return le32_to_cpu(rx); | ||
290 | } | ||
291 | |||
292 | /** | ||
293 | * ks8851_soft_reset - issue one of the soft reset to the device | ||
294 | * @ks: The device state. | ||
295 | * @op: The bit(s) to set in the GRR | ||
296 | * | ||
297 | * Issue the relevant soft-reset command to the device's GRR register | ||
298 | * specified by @op. | ||
299 | * | ||
300 | * Note, the delays are in there as a caution to ensure that the reset | ||
301 | * has time to take effect and then complete. Since the datasheet does | ||
302 | * not currently specify the exact sequence, we have chosen something | ||
303 | * that seems to work with our device. | ||
304 | */ | ||
305 | static void ks8851_soft_reset(struct ks8851_net *ks, unsigned op) | ||
306 | { | ||
307 | ks8851_wrreg16(ks, KS_GRR, op); | ||
308 | mdelay(1); /* wait a short time to effect reset */ | ||
309 | ks8851_wrreg16(ks, KS_GRR, 0); | ||
310 | mdelay(1); /* wait for condition to clear */ | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * ks8851_write_mac_addr - write mac address to device registers | ||
315 | * @dev: The network device | ||
316 | * | ||
317 | * Update the KS8851 MAC address registers from the address in @dev. | ||
318 | * | ||
319 | * This call assumes that the chip is not running, so there is no need to | ||
320 | * shutdown the RXQ process whilst setting this. | ||
321 | */ | ||
322 | static int ks8851_write_mac_addr(struct net_device *dev) | ||
323 | { | ||
324 | struct ks8851_net *ks = netdev_priv(dev); | ||
325 | u16 *mcp = (u16 *)dev->dev_addr; | ||
326 | |||
327 | mutex_lock(&ks->lock); | ||
328 | |||
329 | ks8851_wrreg16(ks, KS_MARL, mcp[0]); | ||
330 | ks8851_wrreg16(ks, KS_MARM, mcp[1]); | ||
331 | ks8851_wrreg16(ks, KS_MARH, mcp[2]); | ||
332 | |||
333 | mutex_unlock(&ks->lock); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | /** | ||
339 | * ks8851_init_mac - initialise the mac address | ||
340 | * @ks: The device structure | ||
341 | * | ||
342 | * Get or create the initial mac address for the device and then set that | ||
343 | * into the station address register. Currently we assume that the device | ||
344 | * does not have a valid mac address in it, and so we use random_ether_addr() | ||
345 | * to create a new one. | ||
346 | * | ||
347 | * In future, the driver should check to see if the device has an EEPROM | ||
348 | * attached and whether that has a valid ethernet address in it. | ||
349 | */ | ||
350 | static void ks8851_init_mac(struct ks8851_net *ks) | ||
351 | { | ||
352 | struct net_device *dev = ks->netdev; | ||
353 | |||
354 | random_ether_addr(dev->dev_addr); | ||
355 | ks8851_write_mac_addr(dev); | ||
356 | } | ||
357 | |||
358 | /** | ||
359 | * ks8851_irq - device interrupt handler | ||
360 | * @irq: Interrupt number passed from the IRQ hnalder. | ||
361 | * @pw: The private word passed to register_irq(), our struct ks8851_net. | ||
362 | * | ||
363 | * Disable the interrupt from happening again until we've processed the | ||
364 | * current status by scheduling ks8851_irq_work(). | ||
365 | */ | ||
366 | static irqreturn_t ks8851_irq(int irq, void *pw) | ||
367 | { | ||
368 | struct ks8851_net *ks = pw; | ||
369 | |||
370 | disable_irq_nosync(irq); | ||
371 | schedule_work(&ks->irq_work); | ||
372 | return IRQ_HANDLED; | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * ks8851_rdfifo - read data from the receive fifo | ||
377 | * @ks: The device state. | ||
378 | * @buff: The buffer address | ||
379 | * @len: The length of the data to read | ||
380 | * | ||
381 | * Issue an RXQ FIFO read command and read the @len ammount of data from | ||
382 | * the FIFO into the buffer specified by @buff. | ||
383 | */ | ||
384 | static void ks8851_rdfifo(struct ks8851_net *ks, u8 *buff, unsigned len) | ||
385 | { | ||
386 | struct spi_transfer *xfer = ks->spi_xfer2; | ||
387 | struct spi_message *msg = &ks->spi_msg2; | ||
388 | u8 txb[1]; | ||
389 | int ret; | ||
390 | |||
391 | if (netif_msg_rx_status(ks)) | ||
392 | ks_dbg(ks, "%s: %d@%p\n", __func__, len, buff); | ||
393 | |||
394 | /* set the operation we're issuing */ | ||
395 | txb[0] = KS_SPIOP_RXFIFO; | ||
396 | |||
397 | xfer->tx_buf = txb; | ||
398 | xfer->rx_buf = NULL; | ||
399 | xfer->len = 1; | ||
400 | |||
401 | xfer++; | ||
402 | xfer->rx_buf = buff; | ||
403 | xfer->tx_buf = NULL; | ||
404 | xfer->len = len; | ||
405 | |||
406 | ret = spi_sync(ks->spidev, msg); | ||
407 | if (ret < 0) | ||
408 | ks_err(ks, "%s: spi_sync() failed\n", __func__); | ||
409 | } | ||
410 | |||
411 | /** | ||
412 | * ks8851_dbg_dumpkkt - dump initial packet contents to debug | ||
413 | * @ks: The device state | ||
414 | * @rxpkt: The data for the received packet | ||
415 | * | ||
416 | * Dump the initial data from the packet to dev_dbg(). | ||
417 | */ | ||
418 | static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt) | ||
419 | { | ||
420 | ks_dbg(ks, "pkt %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", | ||
421 | rxpkt[4], rxpkt[5], rxpkt[6], rxpkt[7], | ||
422 | rxpkt[8], rxpkt[9], rxpkt[10], rxpkt[11], | ||
423 | rxpkt[12], rxpkt[13], rxpkt[14], rxpkt[15]); | ||
424 | } | ||
425 | |||
426 | /** | ||
427 | * ks8851_rx_pkts - receive packets from the host | ||
428 | * @ks: The device information. | ||
429 | * | ||
430 | * This is called from the IRQ work queue when the system detects that there | ||
431 | * are packets in the receive queue. Find out how many packets there are and | ||
432 | * read them from the FIFO. | ||
433 | */ | ||
434 | static void ks8851_rx_pkts(struct ks8851_net *ks) | ||
435 | { | ||
436 | struct sk_buff *skb; | ||
437 | unsigned rxfc; | ||
438 | unsigned rxlen; | ||
439 | unsigned rxstat; | ||
440 | u32 rxh; | ||
441 | u8 *rxpkt; | ||
442 | |||
443 | rxfc = ks8851_rdreg8(ks, KS_RXFC); | ||
444 | |||
445 | if (netif_msg_rx_status(ks)) | ||
446 | ks_dbg(ks, "%s: %d packets\n", __func__, rxfc); | ||
447 | |||
448 | /* Currently we're issuing a read per packet, but we could possibly | ||
449 | * improve the code by issuing a single read, getting the receive | ||
450 | * header, allocating the packet and then reading the packet data | ||
451 | * out in one go. | ||
452 | * | ||
453 | * This form of operation would require us to hold the SPI bus' | ||
454 | * chipselect low during the entie transaction to avoid any | ||
455 | * reset to the data stream comming from the chip. | ||
456 | */ | ||
457 | |||
458 | for (; rxfc != 0; rxfc--) { | ||
459 | rxh = ks8851_rdreg32(ks, KS_RXFHSR); | ||
460 | rxstat = rxh & 0xffff; | ||
461 | rxlen = rxh >> 16; | ||
462 | |||
463 | if (netif_msg_rx_status(ks)) | ||
464 | ks_dbg(ks, "rx: stat 0x%04x, len 0x%04x\n", | ||
465 | rxstat, rxlen); | ||
466 | |||
467 | /* the length of the packet includes the 32bit CRC */ | ||
468 | |||
469 | /* set dma read address */ | ||
470 | ks8851_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI | 0x00); | ||
471 | |||
472 | /* start the packet dma process, and set auto-dequeue rx */ | ||
473 | ks8851_wrreg16(ks, KS_RXQCR, | ||
474 | ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE); | ||
475 | |||
476 | if (rxlen > 0) { | ||
477 | skb = netdev_alloc_skb(ks->netdev, rxlen + 2 + 8); | ||
478 | if (!skb) { | ||
479 | /* todo - dump frame and move on */ | ||
480 | } | ||
481 | |||
482 | /* two bytes to ensure ip is aligned, and four bytes | ||
483 | * for the status header and 4 bytes of garbage */ | ||
484 | skb_reserve(skb, 2 + 4 + 4); | ||
485 | |||
486 | rxpkt = skb_put(skb, rxlen - 4) - 8; | ||
487 | |||
488 | /* align the packet length to 4 bytes, and add 4 bytes | ||
489 | * as we're getting the rx status header as well */ | ||
490 | ks8851_rdfifo(ks, rxpkt, ALIGN(rxlen, 4) + 8); | ||
491 | |||
492 | if (netif_msg_pktdata(ks)) | ||
493 | ks8851_dbg_dumpkkt(ks, rxpkt); | ||
494 | |||
495 | skb->protocol = eth_type_trans(skb, ks->netdev); | ||
496 | netif_rx(skb); | ||
497 | |||
498 | ks->netdev->stats.rx_packets++; | ||
499 | ks->netdev->stats.rx_bytes += rxlen - 4; | ||
500 | } | ||
501 | |||
502 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); | ||
503 | } | ||
504 | } | ||
505 | |||
506 | /** | ||
507 | * ks8851_irq_work - work queue handler for dealing with interrupt requests | ||
508 | * @work: The work structure that was scheduled by schedule_work() | ||
509 | * | ||
510 | * This is the handler invoked when the ks8851_irq() is called to find out | ||
511 | * what happened, as we cannot allow ourselves to sleep whilst waiting for | ||
512 | * anything other process has the chip's lock. | ||
513 | * | ||
514 | * Read the interrupt status, work out what needs to be done and then clear | ||
515 | * any of the interrupts that are not needed. | ||
516 | */ | ||
517 | static void ks8851_irq_work(struct work_struct *work) | ||
518 | { | ||
519 | struct ks8851_net *ks = container_of(work, struct ks8851_net, irq_work); | ||
520 | unsigned status; | ||
521 | unsigned handled = 0; | ||
522 | |||
523 | mutex_lock(&ks->lock); | ||
524 | |||
525 | status = ks8851_rdreg16(ks, KS_ISR); | ||
526 | |||
527 | if (netif_msg_intr(ks)) | ||
528 | dev_dbg(&ks->spidev->dev, "%s: status 0x%04x\n", | ||
529 | __func__, status); | ||
530 | |||
531 | if (status & IRQ_LCI) { | ||
532 | /* should do something about checking link status */ | ||
533 | handled |= IRQ_LCI; | ||
534 | } | ||
535 | |||
536 | if (status & IRQ_LDI) { | ||
537 | u16 pmecr = ks8851_rdreg16(ks, KS_PMECR); | ||
538 | pmecr &= ~PMECR_WKEVT_MASK; | ||
539 | ks8851_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK); | ||
540 | |||
541 | handled |= IRQ_LDI; | ||
542 | } | ||
543 | |||
544 | if (status & IRQ_RXPSI) | ||
545 | handled |= IRQ_RXPSI; | ||
546 | |||
547 | if (status & IRQ_TXI) { | ||
548 | handled |= IRQ_TXI; | ||
549 | |||
550 | /* no lock here, tx queue should have been stopped */ | ||
551 | |||
552 | /* update our idea of how much tx space is available to the | ||
553 | * system */ | ||
554 | ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR); | ||
555 | |||
556 | if (netif_msg_intr(ks)) | ||
557 | ks_dbg(ks, "%s: txspace %d\n", __func__, ks->tx_space); | ||
558 | } | ||
559 | |||
560 | if (status & IRQ_RXI) | ||
561 | handled |= IRQ_RXI; | ||
562 | |||
563 | if (status & IRQ_SPIBEI) { | ||
564 | dev_err(&ks->spidev->dev, "%s: spi bus error\n", __func__); | ||
565 | handled |= IRQ_SPIBEI; | ||
566 | } | ||
567 | |||
568 | ks8851_wrreg16(ks, KS_ISR, handled); | ||
569 | |||
570 | if (status & IRQ_RXI) { | ||
571 | /* the datasheet says to disable the rx interrupt during | ||
572 | * packet read-out, however we're masking the interrupt | ||
573 | * from the device so do not bother masking just the RX | ||
574 | * from the device. */ | ||
575 | |||
576 | ks8851_rx_pkts(ks); | ||
577 | } | ||
578 | |||
579 | /* if something stopped the rx process, probably due to wanting | ||
580 | * to change the rx settings, then do something about restarting | ||
581 | * it. */ | ||
582 | if (status & IRQ_RXPSI) { | ||
583 | struct ks8851_rxctrl *rxc = &ks->rxctrl; | ||
584 | |||
585 | /* update the multicast hash table */ | ||
586 | ks8851_wrreg16(ks, KS_MAHTR0, rxc->mchash[0]); | ||
587 | ks8851_wrreg16(ks, KS_MAHTR1, rxc->mchash[1]); | ||
588 | ks8851_wrreg16(ks, KS_MAHTR2, rxc->mchash[2]); | ||
589 | ks8851_wrreg16(ks, KS_MAHTR3, rxc->mchash[3]); | ||
590 | |||
591 | ks8851_wrreg16(ks, KS_RXCR2, rxc->rxcr2); | ||
592 | ks8851_wrreg16(ks, KS_RXCR1, rxc->rxcr1); | ||
593 | } | ||
594 | |||
595 | mutex_unlock(&ks->lock); | ||
596 | |||
597 | if (status & IRQ_TXI) | ||
598 | netif_wake_queue(ks->netdev); | ||
599 | |||
600 | enable_irq(ks->netdev->irq); | ||
601 | } | ||
602 | |||
603 | /** | ||
604 | * calc_txlen - calculate size of message to send packet | ||
605 | * @len: Lenght of data | ||
606 | * | ||
607 | * Returns the size of the TXFIFO message needed to send | ||
608 | * this packet. | ||
609 | */ | ||
610 | static inline unsigned calc_txlen(unsigned len) | ||
611 | { | ||
612 | return ALIGN(len + 4, 4); | ||
613 | } | ||
614 | |||
615 | /** | ||
616 | * ks8851_wrpkt - write packet to TX FIFO | ||
617 | * @ks: The device state. | ||
618 | * @txp: The sk_buff to transmit. | ||
619 | * @irq: IRQ on completion of the packet. | ||
620 | * | ||
621 | * Send the @txp to the chip. This means creating the relevant packet header | ||
622 | * specifying the length of the packet and the other information the chip | ||
623 | * needs, such as IRQ on completion. Send the header and the packet data to | ||
624 | * the device. | ||
625 | */ | ||
626 | static void ks8851_wrpkt(struct ks8851_net *ks, struct sk_buff *txp, bool irq) | ||
627 | { | ||
628 | struct spi_transfer *xfer = ks->spi_xfer2; | ||
629 | struct spi_message *msg = &ks->spi_msg2; | ||
630 | unsigned fid = 0; | ||
631 | int ret; | ||
632 | |||
633 | if (netif_msg_tx_queued(ks)) | ||
634 | dev_dbg(&ks->spidev->dev, "%s: skb %p, %d@%p, irq %d\n", | ||
635 | __func__, txp, txp->len, txp->data, irq); | ||
636 | |||
637 | fid = ks->fid++; | ||
638 | fid &= TXFR_TXFID_MASK; | ||
639 | |||
640 | if (irq) | ||
641 | fid |= TXFR_TXIC; /* irq on completion */ | ||
642 | |||
643 | /* start header at txb[1] to align txw entries */ | ||
644 | ks->txh.txb[1] = KS_SPIOP_TXFIFO; | ||
645 | ks->txh.txw[1] = cpu_to_le16(fid); | ||
646 | ks->txh.txw[2] = cpu_to_le16(txp->len); | ||
647 | |||
648 | xfer->tx_buf = &ks->txh.txb[1]; | ||
649 | xfer->rx_buf = NULL; | ||
650 | xfer->len = 5; | ||
651 | |||
652 | xfer++; | ||
653 | xfer->tx_buf = txp->data; | ||
654 | xfer->rx_buf = NULL; | ||
655 | xfer->len = ALIGN(txp->len, 4); | ||
656 | |||
657 | ret = spi_sync(ks->spidev, msg); | ||
658 | if (ret < 0) | ||
659 | ks_err(ks, "%s: spi_sync() failed\n", __func__); | ||
660 | } | ||
661 | |||
662 | /** | ||
663 | * ks8851_done_tx - update and then free skbuff after transmitting | ||
664 | * @ks: The device state | ||
665 | * @txb: The buffer transmitted | ||
666 | */ | ||
667 | static void ks8851_done_tx(struct ks8851_net *ks, struct sk_buff *txb) | ||
668 | { | ||
669 | struct net_device *dev = ks->netdev; | ||
670 | |||
671 | dev->stats.tx_bytes += txb->len; | ||
672 | dev->stats.tx_packets++; | ||
673 | |||
674 | dev_kfree_skb(txb); | ||
675 | } | ||
676 | |||
677 | /** | ||
678 | * ks8851_tx_work - process tx packet(s) | ||
679 | * @work: The work strucutre what was scheduled. | ||
680 | * | ||
681 | * This is called when a number of packets have been scheduled for | ||
682 | * transmission and need to be sent to the device. | ||
683 | */ | ||
684 | static void ks8851_tx_work(struct work_struct *work) | ||
685 | { | ||
686 | struct ks8851_net *ks = container_of(work, struct ks8851_net, tx_work); | ||
687 | struct sk_buff *txb; | ||
688 | bool last = false; | ||
689 | |||
690 | mutex_lock(&ks->lock); | ||
691 | |||
692 | while (!last) { | ||
693 | txb = skb_dequeue(&ks->txq); | ||
694 | last = skb_queue_empty(&ks->txq); | ||
695 | |||
696 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); | ||
697 | ks8851_wrpkt(ks, txb, last); | ||
698 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); | ||
699 | ks8851_wrreg16(ks, KS_TXQCR, TXQCR_METFE); | ||
700 | |||
701 | ks8851_done_tx(ks, txb); | ||
702 | } | ||
703 | |||
704 | mutex_unlock(&ks->lock); | ||
705 | } | ||
706 | |||
707 | /** | ||
708 | * ks8851_set_powermode - set power mode of the device | ||
709 | * @ks: The device state | ||
710 | * @pwrmode: The power mode value to write to KS_PMECR. | ||
711 | * | ||
712 | * Change the power mode of the chip. | ||
713 | */ | ||
714 | static void ks8851_set_powermode(struct ks8851_net *ks, unsigned pwrmode) | ||
715 | { | ||
716 | unsigned pmecr; | ||
717 | |||
718 | if (netif_msg_hw(ks)) | ||
719 | ks_dbg(ks, "setting power mode %d\n", pwrmode); | ||
720 | |||
721 | pmecr = ks8851_rdreg16(ks, KS_PMECR); | ||
722 | pmecr &= ~PMECR_PM_MASK; | ||
723 | pmecr |= pwrmode; | ||
724 | |||
725 | ks8851_wrreg16(ks, KS_PMECR, pmecr); | ||
726 | } | ||
727 | |||
728 | /** | ||
729 | * ks8851_net_open - open network device | ||
730 | * @dev: The network device being opened. | ||
731 | * | ||
732 | * Called when the network device is marked active, such as a user executing | ||
733 | * 'ifconfig up' on the device. | ||
734 | */ | ||
735 | static int ks8851_net_open(struct net_device *dev) | ||
736 | { | ||
737 | struct ks8851_net *ks = netdev_priv(dev); | ||
738 | |||
739 | /* lock the card, even if we may not actually be doing anything | ||
740 | * else at the moment */ | ||
741 | mutex_lock(&ks->lock); | ||
742 | |||
743 | if (netif_msg_ifup(ks)) | ||
744 | ks_dbg(ks, "opening %s\n", dev->name); | ||
745 | |||
746 | /* bring chip out of any power saving mode it was in */ | ||
747 | ks8851_set_powermode(ks, PMECR_PM_NORMAL); | ||
748 | |||
749 | /* issue a soft reset to the RX/TX QMU to put it into a known | ||
750 | * state. */ | ||
751 | ks8851_soft_reset(ks, GRR_QMU); | ||
752 | |||
753 | /* setup transmission parameters */ | ||
754 | |||
755 | ks8851_wrreg16(ks, KS_TXCR, (TXCR_TXE | /* enable transmit process */ | ||
756 | TXCR_TXPE | /* pad to min length */ | ||
757 | TXCR_TXCRC | /* add CRC */ | ||
758 | TXCR_TXFCE)); /* enable flow control */ | ||
759 | |||
760 | /* auto-increment tx data, reset tx pointer */ | ||
761 | ks8851_wrreg16(ks, KS_TXFDPR, TXFDPR_TXFPAI); | ||
762 | |||
763 | /* setup receiver control */ | ||
764 | |||
765 | ks8851_wrreg16(ks, KS_RXCR1, (RXCR1_RXPAFMA | /* from mac filter */ | ||
766 | RXCR1_RXFCE | /* enable flow control */ | ||
767 | RXCR1_RXBE | /* broadcast enable */ | ||
768 | RXCR1_RXUE | /* unicast enable */ | ||
769 | RXCR1_RXE)); /* enable rx block */ | ||
770 | |||
771 | /* transfer entire frames out in one go */ | ||
772 | ks8851_wrreg16(ks, KS_RXCR2, RXCR2_SRDBL_FRAME); | ||
773 | |||
774 | /* set receive counter timeouts */ | ||
775 | ks8851_wrreg16(ks, KS_RXDTTR, 1000); /* 1ms after first frame to IRQ */ | ||
776 | ks8851_wrreg16(ks, KS_RXDBCTR, 4096); /* >4Kbytes in buffer to IRQ */ | ||
777 | ks8851_wrreg16(ks, KS_RXFCTR, 10); /* 10 frames to IRQ */ | ||
778 | |||
779 | ks->rc_rxqcr = (RXQCR_RXFCTE | /* IRQ on frame count exceeded */ | ||
780 | RXQCR_RXDBCTE | /* IRQ on byte count exceeded */ | ||
781 | RXQCR_RXDTTE); /* IRQ on time exceeded */ | ||
782 | |||
783 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); | ||
784 | |||
785 | /* clear then enable interrupts */ | ||
786 | |||
787 | #define STD_IRQ (IRQ_LCI | /* Link Change */ \ | ||
788 | IRQ_TXI | /* TX done */ \ | ||
789 | IRQ_RXI | /* RX done */ \ | ||
790 | IRQ_SPIBEI | /* SPI bus error */ \ | ||
791 | IRQ_TXPSI | /* TX process stop */ \ | ||
792 | IRQ_RXPSI) /* RX process stop */ | ||
793 | |||
794 | ks->rc_ier = STD_IRQ; | ||
795 | ks8851_wrreg16(ks, KS_ISR, STD_IRQ); | ||
796 | ks8851_wrreg16(ks, KS_IER, STD_IRQ); | ||
797 | |||
798 | netif_start_queue(ks->netdev); | ||
799 | |||
800 | if (netif_msg_ifup(ks)) | ||
801 | ks_dbg(ks, "network device %s up\n", dev->name); | ||
802 | |||
803 | mutex_unlock(&ks->lock); | ||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | /** | ||
808 | * ks8851_net_stop - close network device | ||
809 | * @dev: The device being closed. | ||
810 | * | ||
811 | * Called to close down a network device which has been active. Cancell any | ||
812 | * work, shutdown the RX and TX process and then place the chip into a low | ||
813 | * power state whilst it is not being used. | ||
814 | */ | ||
815 | static int ks8851_net_stop(struct net_device *dev) | ||
816 | { | ||
817 | struct ks8851_net *ks = netdev_priv(dev); | ||
818 | |||
819 | if (netif_msg_ifdown(ks)) | ||
820 | ks_info(ks, "%s: shutting down\n", dev->name); | ||
821 | |||
822 | netif_stop_queue(dev); | ||
823 | |||
824 | mutex_lock(&ks->lock); | ||
825 | |||
826 | /* stop any outstanding work */ | ||
827 | flush_work(&ks->irq_work); | ||
828 | flush_work(&ks->tx_work); | ||
829 | flush_work(&ks->rxctrl_work); | ||
830 | |||
831 | /* turn off the IRQs and ack any outstanding */ | ||
832 | ks8851_wrreg16(ks, KS_IER, 0x0000); | ||
833 | ks8851_wrreg16(ks, KS_ISR, 0xffff); | ||
834 | |||
835 | /* shutdown RX process */ | ||
836 | ks8851_wrreg16(ks, KS_RXCR1, 0x0000); | ||
837 | |||
838 | /* shutdown TX process */ | ||
839 | ks8851_wrreg16(ks, KS_TXCR, 0x0000); | ||
840 | |||
841 | /* set powermode to soft power down to save power */ | ||
842 | ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); | ||
843 | |||
844 | /* ensure any queued tx buffers are dumped */ | ||
845 | while (!skb_queue_empty(&ks->txq)) { | ||
846 | struct sk_buff *txb = skb_dequeue(&ks->txq); | ||
847 | |||
848 | if (netif_msg_ifdown(ks)) | ||
849 | ks_dbg(ks, "%s: freeing txb %p\n", __func__, txb); | ||
850 | |||
851 | dev_kfree_skb(txb); | ||
852 | } | ||
853 | |||
854 | mutex_unlock(&ks->lock); | ||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | /** | ||
859 | * ks8851_start_xmit - transmit packet | ||
860 | * @skb: The buffer to transmit | ||
861 | * @dev: The device used to transmit the packet. | ||
862 | * | ||
863 | * Called by the network layer to transmit the @skb. Queue the packet for | ||
864 | * the device and schedule the necessary work to transmit the packet when | ||
865 | * it is free. | ||
866 | * | ||
867 | * We do this to firstly avoid sleeping with the network device locked, | ||
868 | * and secondly so we can round up more than one packet to transmit which | ||
869 | * means we can try and avoid generating too many transmit done interrupts. | ||
870 | */ | ||
871 | static int ks8851_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
872 | { | ||
873 | struct ks8851_net *ks = netdev_priv(dev); | ||
874 | unsigned needed = calc_txlen(skb->len); | ||
875 | int ret = NETDEV_TX_OK; | ||
876 | |||
877 | if (netif_msg_tx_queued(ks)) | ||
878 | ks_dbg(ks, "%s: skb %p, %d@%p\n", __func__, | ||
879 | skb, skb->len, skb->data); | ||
880 | |||
881 | spin_lock(&ks->statelock); | ||
882 | |||
883 | if (needed > ks->tx_space) { | ||
884 | netif_stop_queue(dev); | ||
885 | ret = NETDEV_TX_BUSY; | ||
886 | } else { | ||
887 | ks->tx_space -= needed; | ||
888 | skb_queue_tail(&ks->txq, skb); | ||
889 | } | ||
890 | |||
891 | spin_unlock(&ks->statelock); | ||
892 | schedule_work(&ks->tx_work); | ||
893 | |||
894 | return ret; | ||
895 | } | ||
896 | |||
897 | /** | ||
898 | * ks8851_rxctrl_work - work handler to change rx mode | ||
899 | * @work: The work structure this belongs to. | ||
900 | * | ||
901 | * Lock the device and issue the necessary changes to the receive mode from | ||
902 | * the network device layer. This is done so that we can do this without | ||
903 | * having to sleep whilst holding the network device lock. | ||
904 | * | ||
905 | * Since the recommendation from Micrel is that the RXQ is shutdown whilst the | ||
906 | * receive parameters are programmed, we issue a write to disable the RXQ and | ||
907 | * then wait for the interrupt handler to be triggered once the RXQ shutdown is | ||
908 | * complete. The interrupt handler then writes the new values into the chip. | ||
909 | */ | ||
910 | static void ks8851_rxctrl_work(struct work_struct *work) | ||
911 | { | ||
912 | struct ks8851_net *ks = container_of(work, struct ks8851_net, rxctrl_work); | ||
913 | |||
914 | mutex_lock(&ks->lock); | ||
915 | |||
916 | /* need to shutdown RXQ before modifying filter parameters */ | ||
917 | ks8851_wrreg16(ks, KS_RXCR1, 0x00); | ||
918 | |||
919 | mutex_unlock(&ks->lock); | ||
920 | } | ||
921 | |||
922 | static void ks8851_set_rx_mode(struct net_device *dev) | ||
923 | { | ||
924 | struct ks8851_net *ks = netdev_priv(dev); | ||
925 | struct ks8851_rxctrl rxctrl; | ||
926 | |||
927 | memset(&rxctrl, 0, sizeof(rxctrl)); | ||
928 | |||
929 | if (dev->flags & IFF_PROMISC) { | ||
930 | /* interface to receive everything */ | ||
931 | |||
932 | rxctrl.rxcr1 = RXCR1_RXAE | RXCR1_RXINVF; | ||
933 | } else if (dev->flags & IFF_ALLMULTI) { | ||
934 | /* accept all multicast packets */ | ||
935 | |||
936 | rxctrl.rxcr1 = (RXCR1_RXME | RXCR1_RXAE | | ||
937 | RXCR1_RXPAFMA | RXCR1_RXMAFMA); | ||
938 | } else if (dev->flags & IFF_MULTICAST && dev->mc_count > 0) { | ||
939 | struct dev_mc_list *mcptr = dev->mc_list; | ||
940 | u32 crc; | ||
941 | int i; | ||
942 | |||
943 | /* accept some multicast */ | ||
944 | |||
945 | for (i = dev->mc_count; i > 0; i--) { | ||
946 | crc = ether_crc(ETH_ALEN, mcptr->dmi_addr); | ||
947 | crc >>= (32 - 6); /* get top six bits */ | ||
948 | |||
949 | rxctrl.mchash[crc >> 4] |= (1 << (crc & 0xf)); | ||
950 | mcptr = mcptr->next; | ||
951 | } | ||
952 | |||
953 | rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXAE | RXCR1_RXPAFMA; | ||
954 | } else { | ||
955 | /* just accept broadcast / unicast */ | ||
956 | rxctrl.rxcr1 = RXCR1_RXPAFMA; | ||
957 | } | ||
958 | |||
959 | rxctrl.rxcr1 |= (RXCR1_RXUE | /* unicast enable */ | ||
960 | RXCR1_RXBE | /* broadcast enable */ | ||
961 | RXCR1_RXE | /* RX process enable */ | ||
962 | RXCR1_RXFCE); /* enable flow control */ | ||
963 | |||
964 | rxctrl.rxcr2 |= RXCR2_SRDBL_FRAME; | ||
965 | |||
966 | /* schedule work to do the actual set of the data if needed */ | ||
967 | |||
968 | spin_lock(&ks->statelock); | ||
969 | |||
970 | if (memcmp(&rxctrl, &ks->rxctrl, sizeof(rxctrl)) != 0) { | ||
971 | memcpy(&ks->rxctrl, &rxctrl, sizeof(ks->rxctrl)); | ||
972 | schedule_work(&ks->rxctrl_work); | ||
973 | } | ||
974 | |||
975 | spin_unlock(&ks->statelock); | ||
976 | } | ||
977 | |||
978 | static int ks8851_set_mac_address(struct net_device *dev, void *addr) | ||
979 | { | ||
980 | struct sockaddr *sa = addr; | ||
981 | |||
982 | if (netif_running(dev)) | ||
983 | return -EBUSY; | ||
984 | |||
985 | if (!is_valid_ether_addr(sa->sa_data)) | ||
986 | return -EADDRNOTAVAIL; | ||
987 | |||
988 | memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN); | ||
989 | return ks8851_write_mac_addr(dev); | ||
990 | } | ||
991 | |||
992 | static int ks8851_net_ioctl(struct net_device *dev, struct ifreq *req, int cmd) | ||
993 | { | ||
994 | struct ks8851_net *ks = netdev_priv(dev); | ||
995 | |||
996 | if (!netif_running(dev)) | ||
997 | return -EINVAL; | ||
998 | |||
999 | return generic_mii_ioctl(&ks->mii, if_mii(req), cmd, NULL); | ||
1000 | } | ||
1001 | |||
1002 | static const struct net_device_ops ks8851_netdev_ops = { | ||
1003 | .ndo_open = ks8851_net_open, | ||
1004 | .ndo_stop = ks8851_net_stop, | ||
1005 | .ndo_do_ioctl = ks8851_net_ioctl, | ||
1006 | .ndo_start_xmit = ks8851_start_xmit, | ||
1007 | .ndo_set_mac_address = ks8851_set_mac_address, | ||
1008 | .ndo_set_rx_mode = ks8851_set_rx_mode, | ||
1009 | .ndo_change_mtu = eth_change_mtu, | ||
1010 | .ndo_validate_addr = eth_validate_addr, | ||
1011 | }; | ||
1012 | |||
1013 | /* ethtool support */ | ||
1014 | |||
1015 | static void ks8851_get_drvinfo(struct net_device *dev, | ||
1016 | struct ethtool_drvinfo *di) | ||
1017 | { | ||
1018 | strlcpy(di->driver, "KS8851", sizeof(di->driver)); | ||
1019 | strlcpy(di->version, "1.00", sizeof(di->version)); | ||
1020 | strlcpy(di->bus_info, dev_name(dev->dev.parent), sizeof(di->bus_info)); | ||
1021 | } | ||
1022 | |||
1023 | static u32 ks8851_get_msglevel(struct net_device *dev) | ||
1024 | { | ||
1025 | struct ks8851_net *ks = netdev_priv(dev); | ||
1026 | return ks->msg_enable; | ||
1027 | } | ||
1028 | |||
1029 | static void ks8851_set_msglevel(struct net_device *dev, u32 to) | ||
1030 | { | ||
1031 | struct ks8851_net *ks = netdev_priv(dev); | ||
1032 | ks->msg_enable = to; | ||
1033 | } | ||
1034 | |||
1035 | static int ks8851_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
1036 | { | ||
1037 | struct ks8851_net *ks = netdev_priv(dev); | ||
1038 | return mii_ethtool_gset(&ks->mii, cmd); | ||
1039 | } | ||
1040 | |||
1041 | static int ks8851_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
1042 | { | ||
1043 | struct ks8851_net *ks = netdev_priv(dev); | ||
1044 | return mii_ethtool_sset(&ks->mii, cmd); | ||
1045 | } | ||
1046 | |||
1047 | static u32 ks8851_get_link(struct net_device *dev) | ||
1048 | { | ||
1049 | struct ks8851_net *ks = netdev_priv(dev); | ||
1050 | return mii_link_ok(&ks->mii); | ||
1051 | } | ||
1052 | |||
1053 | static int ks8851_nway_reset(struct net_device *dev) | ||
1054 | { | ||
1055 | struct ks8851_net *ks = netdev_priv(dev); | ||
1056 | return mii_nway_restart(&ks->mii); | ||
1057 | } | ||
1058 | |||
1059 | static const struct ethtool_ops ks8851_ethtool_ops = { | ||
1060 | .get_drvinfo = ks8851_get_drvinfo, | ||
1061 | .get_msglevel = ks8851_get_msglevel, | ||
1062 | .set_msglevel = ks8851_set_msglevel, | ||
1063 | .get_settings = ks8851_get_settings, | ||
1064 | .set_settings = ks8851_set_settings, | ||
1065 | .get_link = ks8851_get_link, | ||
1066 | .nway_reset = ks8851_nway_reset, | ||
1067 | }; | ||
1068 | |||
1069 | /* MII interface controls */ | ||
1070 | |||
1071 | /** | ||
1072 | * ks8851_phy_reg - convert MII register into a KS8851 register | ||
1073 | * @reg: MII register number. | ||
1074 | * | ||
1075 | * Return the KS8851 register number for the corresponding MII PHY register | ||
1076 | * if possible. Return zero if the MII register has no direct mapping to the | ||
1077 | * KS8851 register set. | ||
1078 | */ | ||
1079 | static int ks8851_phy_reg(int reg) | ||
1080 | { | ||
1081 | switch (reg) { | ||
1082 | case MII_BMCR: | ||
1083 | return KS_P1MBCR; | ||
1084 | case MII_BMSR: | ||
1085 | return KS_P1MBSR; | ||
1086 | case MII_PHYSID1: | ||
1087 | return KS_PHY1ILR; | ||
1088 | case MII_PHYSID2: | ||
1089 | return KS_PHY1IHR; | ||
1090 | case MII_ADVERTISE: | ||
1091 | return KS_P1ANAR; | ||
1092 | case MII_LPA: | ||
1093 | return KS_P1ANLPR; | ||
1094 | } | ||
1095 | |||
1096 | return 0x0; | ||
1097 | } | ||
1098 | |||
1099 | /** | ||
1100 | * ks8851_phy_read - MII interface PHY register read. | ||
1101 | * @dev: The network device the PHY is on. | ||
1102 | * @phy_addr: Address of PHY (ignored as we only have one) | ||
1103 | * @reg: The register to read. | ||
1104 | * | ||
1105 | * This call reads data from the PHY register specified in @reg. Since the | ||
1106 | * device does not support all the MII registers, the non-existant values | ||
1107 | * are always returned as zero. | ||
1108 | * | ||
1109 | * We return zero for unsupported registers as the MII code does not check | ||
1110 | * the value returned for any error status, and simply returns it to the | ||
1111 | * caller. The mii-tool that the driver was tested with takes any -ve error | ||
1112 | * as real PHY capabilities, thus displaying incorrect data to the user. | ||
1113 | */ | ||
1114 | static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg) | ||
1115 | { | ||
1116 | struct ks8851_net *ks = netdev_priv(dev); | ||
1117 | int ksreg; | ||
1118 | int result; | ||
1119 | |||
1120 | ksreg = ks8851_phy_reg(reg); | ||
1121 | if (!ksreg) | ||
1122 | return 0x0; /* no error return allowed, so use zero */ | ||
1123 | |||
1124 | mutex_lock(&ks->lock); | ||
1125 | result = ks8851_rdreg16(ks, ksreg); | ||
1126 | mutex_unlock(&ks->lock); | ||
1127 | |||
1128 | return result; | ||
1129 | } | ||
1130 | |||
1131 | static void ks8851_phy_write(struct net_device *dev, | ||
1132 | int phy, int reg, int value) | ||
1133 | { | ||
1134 | struct ks8851_net *ks = netdev_priv(dev); | ||
1135 | int ksreg; | ||
1136 | |||
1137 | ksreg = ks8851_phy_reg(reg); | ||
1138 | if (ksreg) { | ||
1139 | mutex_lock(&ks->lock); | ||
1140 | ks8851_wrreg16(ks, ksreg, value); | ||
1141 | mutex_unlock(&ks->lock); | ||
1142 | } | ||
1143 | } | ||
1144 | |||
1145 | /** | ||
1146 | * ks8851_read_selftest - read the selftest memory info. | ||
1147 | * @ks: The device state | ||
1148 | * | ||
1149 | * Read and check the TX/RX memory selftest information. | ||
1150 | */ | ||
1151 | static int ks8851_read_selftest(struct ks8851_net *ks) | ||
1152 | { | ||
1153 | unsigned both_done = MBIR_TXMBF | MBIR_RXMBF; | ||
1154 | int ret = 0; | ||
1155 | unsigned rd; | ||
1156 | |||
1157 | rd = ks8851_rdreg16(ks, KS_MBIR); | ||
1158 | |||
1159 | if ((rd & both_done) != both_done) { | ||
1160 | ks_warn(ks, "Memory selftest not finished\n"); | ||
1161 | return 0; | ||
1162 | } | ||
1163 | |||
1164 | if (rd & MBIR_TXMBFA) { | ||
1165 | ks_err(ks, "TX memory selftest fail\n"); | ||
1166 | ret |= 1; | ||
1167 | } | ||
1168 | |||
1169 | if (rd & MBIR_RXMBFA) { | ||
1170 | ks_err(ks, "RX memory selftest fail\n"); | ||
1171 | ret |= 2; | ||
1172 | } | ||
1173 | |||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1177 | /* driver bus management functions */ | ||
1178 | |||
1179 | static int __devinit ks8851_probe(struct spi_device *spi) | ||
1180 | { | ||
1181 | struct net_device *ndev; | ||
1182 | struct ks8851_net *ks; | ||
1183 | int ret; | ||
1184 | |||
1185 | ndev = alloc_etherdev(sizeof(struct ks8851_net)); | ||
1186 | if (!ndev) { | ||
1187 | dev_err(&spi->dev, "failed to alloc ethernet device\n"); | ||
1188 | return -ENOMEM; | ||
1189 | } | ||
1190 | |||
1191 | spi->bits_per_word = 8; | ||
1192 | |||
1193 | ks = netdev_priv(ndev); | ||
1194 | |||
1195 | ks->netdev = ndev; | ||
1196 | ks->spidev = spi; | ||
1197 | ks->tx_space = 6144; | ||
1198 | |||
1199 | mutex_init(&ks->lock); | ||
1200 | spin_lock_init(&ks->statelock); | ||
1201 | |||
1202 | INIT_WORK(&ks->tx_work, ks8851_tx_work); | ||
1203 | INIT_WORK(&ks->irq_work, ks8851_irq_work); | ||
1204 | INIT_WORK(&ks->rxctrl_work, ks8851_rxctrl_work); | ||
1205 | |||
1206 | /* initialise pre-made spi transfer messages */ | ||
1207 | |||
1208 | spi_message_init(&ks->spi_msg1); | ||
1209 | spi_message_add_tail(&ks->spi_xfer1, &ks->spi_msg1); | ||
1210 | |||
1211 | spi_message_init(&ks->spi_msg2); | ||
1212 | spi_message_add_tail(&ks->spi_xfer2[0], &ks->spi_msg2); | ||
1213 | spi_message_add_tail(&ks->spi_xfer2[1], &ks->spi_msg2); | ||
1214 | |||
1215 | /* setup mii state */ | ||
1216 | ks->mii.dev = ndev; | ||
1217 | ks->mii.phy_id = 1, | ||
1218 | ks->mii.phy_id_mask = 1; | ||
1219 | ks->mii.reg_num_mask = 0xf; | ||
1220 | ks->mii.mdio_read = ks8851_phy_read; | ||
1221 | ks->mii.mdio_write = ks8851_phy_write; | ||
1222 | |||
1223 | dev_info(&spi->dev, "message enable is %d\n", msg_enable); | ||
1224 | |||
1225 | /* set the default message enable */ | ||
1226 | ks->msg_enable = netif_msg_init(msg_enable, (NETIF_MSG_DRV | | ||
1227 | NETIF_MSG_PROBE | | ||
1228 | NETIF_MSG_LINK)); | ||
1229 | |||
1230 | skb_queue_head_init(&ks->txq); | ||
1231 | |||
1232 | SET_ETHTOOL_OPS(ndev, &ks8851_ethtool_ops); | ||
1233 | SET_NETDEV_DEV(ndev, &spi->dev); | ||
1234 | |||
1235 | dev_set_drvdata(&spi->dev, ks); | ||
1236 | |||
1237 | ndev->if_port = IF_PORT_100BASET; | ||
1238 | ndev->netdev_ops = &ks8851_netdev_ops; | ||
1239 | ndev->irq = spi->irq; | ||
1240 | |||
1241 | /* simple check for a valid chip being connected to the bus */ | ||
1242 | |||
1243 | if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) { | ||
1244 | dev_err(&spi->dev, "failed to read device ID\n"); | ||
1245 | ret = -ENODEV; | ||
1246 | goto err_id; | ||
1247 | } | ||
1248 | |||
1249 | ks8851_read_selftest(ks); | ||
1250 | ks8851_init_mac(ks); | ||
1251 | |||
1252 | ret = request_irq(spi->irq, ks8851_irq, IRQF_TRIGGER_LOW, | ||
1253 | ndev->name, ks); | ||
1254 | if (ret < 0) { | ||
1255 | dev_err(&spi->dev, "failed to get irq\n"); | ||
1256 | goto err_irq; | ||
1257 | } | ||
1258 | |||
1259 | ret = register_netdev(ndev); | ||
1260 | if (ret) { | ||
1261 | dev_err(&spi->dev, "failed to register network device\n"); | ||
1262 | goto err_netdev; | ||
1263 | } | ||
1264 | |||
1265 | dev_info(&spi->dev, "revision %d, MAC %pM, IRQ %d\n", | ||
1266 | CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)), | ||
1267 | ndev->dev_addr, ndev->irq); | ||
1268 | |||
1269 | return 0; | ||
1270 | |||
1271 | |||
1272 | err_netdev: | ||
1273 | free_irq(ndev->irq, ndev); | ||
1274 | |||
1275 | err_id: | ||
1276 | err_irq: | ||
1277 | free_netdev(ndev); | ||
1278 | return ret; | ||
1279 | } | ||
1280 | |||
1281 | static int __devexit ks8851_remove(struct spi_device *spi) | ||
1282 | { | ||
1283 | struct ks8851_net *priv = dev_get_drvdata(&spi->dev); | ||
1284 | |||
1285 | if (netif_msg_drv(priv)) | ||
1286 | dev_info(&spi->dev, "remove"); | ||
1287 | |||
1288 | unregister_netdev(priv->netdev); | ||
1289 | free_irq(spi->irq, priv); | ||
1290 | free_netdev(priv->netdev); | ||
1291 | |||
1292 | return 0; | ||
1293 | } | ||
1294 | |||
1295 | static struct spi_driver ks8851_driver = { | ||
1296 | .driver = { | ||
1297 | .name = "ks8851", | ||
1298 | .owner = THIS_MODULE, | ||
1299 | }, | ||
1300 | .probe = ks8851_probe, | ||
1301 | .remove = __devexit_p(ks8851_remove), | ||
1302 | }; | ||
1303 | |||
1304 | static int __init ks8851_init(void) | ||
1305 | { | ||
1306 | return spi_register_driver(&ks8851_driver); | ||
1307 | } | ||
1308 | |||
1309 | static void __exit ks8851_exit(void) | ||
1310 | { | ||
1311 | spi_unregister_driver(&ks8851_driver); | ||
1312 | } | ||
1313 | |||
1314 | module_init(ks8851_init); | ||
1315 | module_exit(ks8851_exit); | ||
1316 | |||
1317 | MODULE_DESCRIPTION("KS8851 Network driver"); | ||
1318 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
1319 | MODULE_LICENSE("GPL"); | ||
1320 | |||
1321 | module_param_named(message, msg_enable, int, 0); | ||
1322 | MODULE_PARM_DESC(message, "Message verbosity level (0=none, 31=all)"); | ||
diff --git a/drivers/net/ks8851.h b/drivers/net/ks8851.h new file mode 100644 index 000000000000..85abe147afbf --- /dev/null +++ b/drivers/net/ks8851.h | |||
@@ -0,0 +1,296 @@ | |||
1 | /* drivers/net/ks8851.h | ||
2 | * | ||
3 | * Copyright 2009 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * KS8851 register definitions | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #define KS_CCR 0x08 | ||
14 | #define CCR_EEPROM (1 << 9) | ||
15 | #define CCR_SPI (1 << 8) | ||
16 | #define CCR_32PIN (1 << 0) | ||
17 | |||
18 | /* MAC address registers */ | ||
19 | #define KS_MARL 0x10 | ||
20 | #define KS_MARM 0x12 | ||
21 | #define KS_MARH 0x14 | ||
22 | |||
23 | #define KS_OBCR 0x20 | ||
24 | #define OBCR_ODS_16mA (1 << 6) | ||
25 | |||
26 | #define KS_EEPCR 0x22 | ||
27 | #define EEPCR_EESA (1 << 4) | ||
28 | #define EEPCR_EESB (1 << 3) | ||
29 | #define EEPCR_EEDO (1 << 2) | ||
30 | #define EEPCR_EESCK (1 << 1) | ||
31 | #define EEPCR_EECS (1 << 0) | ||
32 | |||
33 | #define KS_MBIR 0x24 | ||
34 | #define MBIR_TXMBF (1 << 12) | ||
35 | #define MBIR_TXMBFA (1 << 11) | ||
36 | #define MBIR_RXMBF (1 << 4) | ||
37 | #define MBIR_RXMBFA (1 << 3) | ||
38 | |||
39 | #define KS_GRR 0x26 | ||
40 | #define GRR_QMU (1 << 1) | ||
41 | #define GRR_GSR (1 << 0) | ||
42 | |||
43 | #define KS_WFCR 0x2A | ||
44 | #define WFCR_MPRXE (1 << 7) | ||
45 | #define WFCR_WF3E (1 << 3) | ||
46 | #define WFCR_WF2E (1 << 2) | ||
47 | #define WFCR_WF1E (1 << 1) | ||
48 | #define WFCR_WF0E (1 << 0) | ||
49 | |||
50 | #define KS_WF0CRC0 0x30 | ||
51 | #define KS_WF0CRC1 0x32 | ||
52 | #define KS_WF0BM0 0x34 | ||
53 | #define KS_WF0BM1 0x36 | ||
54 | #define KS_WF0BM2 0x38 | ||
55 | #define KS_WF0BM3 0x3A | ||
56 | |||
57 | #define KS_WF1CRC0 0x40 | ||
58 | #define KS_WF1CRC1 0x42 | ||
59 | #define KS_WF1BM0 0x44 | ||
60 | #define KS_WF1BM1 0x46 | ||
61 | #define KS_WF1BM2 0x48 | ||
62 | #define KS_WF1BM3 0x4A | ||
63 | |||
64 | #define KS_WF2CRC0 0x50 | ||
65 | #define KS_WF2CRC1 0x52 | ||
66 | #define KS_WF2BM0 0x54 | ||
67 | #define KS_WF2BM1 0x56 | ||
68 | #define KS_WF2BM2 0x58 | ||
69 | #define KS_WF2BM3 0x5A | ||
70 | |||
71 | #define KS_WF3CRC0 0x60 | ||
72 | #define KS_WF3CRC1 0x62 | ||
73 | #define KS_WF3BM0 0x64 | ||
74 | #define KS_WF3BM1 0x66 | ||
75 | #define KS_WF3BM2 0x68 | ||
76 | #define KS_WF3BM3 0x6A | ||
77 | |||
78 | #define KS_TXCR 0x70 | ||
79 | #define TXCR_TCGICMP (1 << 8) | ||
80 | #define TXCR_TCGUDP (1 << 7) | ||
81 | #define TXCR_TCGTCP (1 << 6) | ||
82 | #define TXCR_TCGIP (1 << 5) | ||
83 | #define TXCR_FTXQ (1 << 4) | ||
84 | #define TXCR_TXFCE (1 << 3) | ||
85 | #define TXCR_TXPE (1 << 2) | ||
86 | #define TXCR_TXCRC (1 << 1) | ||
87 | #define TXCR_TXE (1 << 0) | ||
88 | |||
89 | #define KS_TXSR 0x72 | ||
90 | #define TXSR_TXLC (1 << 13) | ||
91 | #define TXSR_TXMC (1 << 12) | ||
92 | #define TXSR_TXFID_MASK (0x3f << 0) | ||
93 | #define TXSR_TXFID_SHIFT (0) | ||
94 | #define TXSR_TXFID_GET(_v) (((_v) >> 0) & 0x3f) | ||
95 | |||
96 | #define KS_RXCR1 0x74 | ||
97 | #define RXCR1_FRXQ (1 << 15) | ||
98 | #define RXCR1_RXUDPFCC (1 << 14) | ||
99 | #define RXCR1_RXTCPFCC (1 << 13) | ||
100 | #define RXCR1_RXIPFCC (1 << 12) | ||
101 | #define RXCR1_RXPAFMA (1 << 11) | ||
102 | #define RXCR1_RXFCE (1 << 10) | ||
103 | #define RXCR1_RXEFE (1 << 9) | ||
104 | #define RXCR1_RXMAFMA (1 << 8) | ||
105 | #define RXCR1_RXBE (1 << 7) | ||
106 | #define RXCR1_RXME (1 << 6) | ||
107 | #define RXCR1_RXUE (1 << 5) | ||
108 | #define RXCR1_RXAE (1 << 4) | ||
109 | #define RXCR1_RXINVF (1 << 1) | ||
110 | #define RXCR1_RXE (1 << 0) | ||
111 | |||
112 | #define KS_RXCR2 0x76 | ||
113 | #define RXCR2_SRDBL_MASK (0x7 << 5) | ||
114 | #define RXCR2_SRDBL_SHIFT (5) | ||
115 | #define RXCR2_SRDBL_4B (0x0 << 5) | ||
116 | #define RXCR2_SRDBL_8B (0x1 << 5) | ||
117 | #define RXCR2_SRDBL_16B (0x2 << 5) | ||
118 | #define RXCR2_SRDBL_32B (0x3 << 5) | ||
119 | #define RXCR2_SRDBL_FRAME (0x4 << 5) | ||
120 | #define RXCR2_IUFFP (1 << 4) | ||
121 | #define RXCR2_RXIUFCEZ (1 << 3) | ||
122 | #define RXCR2_UDPLFE (1 << 2) | ||
123 | #define RXCR2_RXICMPFCC (1 << 1) | ||
124 | #define RXCR2_RXSAF (1 << 0) | ||
125 | |||
126 | #define KS_TXMIR 0x78 | ||
127 | |||
128 | #define KS_RXFHSR 0x7C | ||
129 | #define RXFSHR_RXFV (1 << 15) | ||
130 | #define RXFSHR_RXICMPFCS (1 << 13) | ||
131 | #define RXFSHR_RXIPFCS (1 << 12) | ||
132 | #define RXFSHR_RXTCPFCS (1 << 11) | ||
133 | #define RXFSHR_RXUDPFCS (1 << 10) | ||
134 | #define RXFSHR_RXBF (1 << 7) | ||
135 | #define RXFSHR_RXMF (1 << 6) | ||
136 | #define RXFSHR_RXUF (1 << 5) | ||
137 | #define RXFSHR_RXMR (1 << 4) | ||
138 | #define RXFSHR_RXFT (1 << 3) | ||
139 | #define RXFSHR_RXFTL (1 << 2) | ||
140 | #define RXFSHR_RXRF (1 << 1) | ||
141 | #define RXFSHR_RXCE (1 << 0) | ||
142 | |||
143 | #define KS_RXFHBCR 0x7E | ||
144 | #define KS_TXQCR 0x80 | ||
145 | #define TXQCR_AETFE (1 << 2) | ||
146 | #define TXQCR_TXQMAM (1 << 1) | ||
147 | #define TXQCR_METFE (1 << 0) | ||
148 | |||
149 | #define KS_RXQCR 0x82 | ||
150 | #define RXQCR_RXDTTS (1 << 12) | ||
151 | #define RXQCR_RXDBCTS (1 << 11) | ||
152 | #define RXQCR_RXFCTS (1 << 10) | ||
153 | #define RXQCR_RXIPHTOE (1 << 9) | ||
154 | #define RXQCR_RXDTTE (1 << 7) | ||
155 | #define RXQCR_RXDBCTE (1 << 6) | ||
156 | #define RXQCR_RXFCTE (1 << 5) | ||
157 | #define RXQCR_ADRFE (1 << 4) | ||
158 | #define RXQCR_SDA (1 << 3) | ||
159 | #define RXQCR_RRXEF (1 << 0) | ||
160 | |||
161 | #define KS_TXFDPR 0x84 | ||
162 | #define TXFDPR_TXFPAI (1 << 14) | ||
163 | #define TXFDPR_TXFP_MASK (0x7ff << 0) | ||
164 | #define TXFDPR_TXFP_SHIFT (0) | ||
165 | |||
166 | #define KS_RXFDPR 0x86 | ||
167 | #define RXFDPR_RXFPAI (1 << 14) | ||
168 | |||
169 | #define KS_RXDTTR 0x8C | ||
170 | #define KS_RXDBCTR 0x8E | ||
171 | |||
172 | #define KS_IER 0x90 | ||
173 | #define KS_ISR 0x92 | ||
174 | #define IRQ_LCI (1 << 15) | ||
175 | #define IRQ_TXI (1 << 14) | ||
176 | #define IRQ_RXI (1 << 13) | ||
177 | #define IRQ_RXOI (1 << 11) | ||
178 | #define IRQ_TXPSI (1 << 9) | ||
179 | #define IRQ_RXPSI (1 << 8) | ||
180 | #define IRQ_TXSAI (1 << 6) | ||
181 | #define IRQ_RXWFDI (1 << 5) | ||
182 | #define IRQ_RXMPDI (1 << 4) | ||
183 | #define IRQ_LDI (1 << 3) | ||
184 | #define IRQ_EDI (1 << 2) | ||
185 | #define IRQ_SPIBEI (1 << 1) | ||
186 | #define IRQ_DEDI (1 << 0) | ||
187 | |||
188 | #define KS_RXFCTR 0x9C | ||
189 | #define KS_RXFC 0x9D | ||
190 | #define RXFCTR_RXFC_MASK (0xff << 8) | ||
191 | #define RXFCTR_RXFC_SHIFT (8) | ||
192 | #define RXFCTR_RXFC_GET(_v) (((_v) >> 8) & 0xff) | ||
193 | #define RXFCTR_RXFCT_MASK (0xff << 0) | ||
194 | #define RXFCTR_RXFCT_SHIFT (0) | ||
195 | |||
196 | #define KS_TXNTFSR 0x9E | ||
197 | |||
198 | #define KS_MAHTR0 0xA0 | ||
199 | #define KS_MAHTR1 0xA2 | ||
200 | #define KS_MAHTR2 0xA4 | ||
201 | #define KS_MAHTR3 0xA6 | ||
202 | |||
203 | #define KS_FCLWR 0xB0 | ||
204 | #define KS_FCHWR 0xB2 | ||
205 | #define KS_FCOWR 0xB4 | ||
206 | |||
207 | #define KS_CIDER 0xC0 | ||
208 | #define CIDER_ID 0x8870 | ||
209 | #define CIDER_REV_MASK (0x7 << 1) | ||
210 | #define CIDER_REV_SHIFT (1) | ||
211 | #define CIDER_REV_GET(_v) (((_v) >> 1) & 0x7) | ||
212 | |||
213 | #define KS_CGCR 0xC6 | ||
214 | |||
215 | #define KS_IACR 0xC8 | ||
216 | #define IACR_RDEN (1 << 12) | ||
217 | #define IACR_TSEL_MASK (0x3 << 10) | ||
218 | #define IACR_TSEL_SHIFT (10) | ||
219 | #define IACR_TSEL_MIB (0x3 << 10) | ||
220 | #define IACR_ADDR_MASK (0x1f << 0) | ||
221 | #define IACR_ADDR_SHIFT (0) | ||
222 | |||
223 | #define KS_IADLR 0xD0 | ||
224 | #define KS_IAHDR 0xD2 | ||
225 | |||
226 | #define KS_PMECR 0xD4 | ||
227 | #define PMECR_PME_DELAY (1 << 14) | ||
228 | #define PMECR_PME_POL (1 << 12) | ||
229 | #define PMECR_WOL_WAKEUP (1 << 11) | ||
230 | #define PMECR_WOL_MAGICPKT (1 << 10) | ||
231 | #define PMECR_WOL_LINKUP (1 << 9) | ||
232 | #define PMECR_WOL_ENERGY (1 << 8) | ||
233 | #define PMECR_AUTO_WAKE_EN (1 << 7) | ||
234 | #define PMECR_WAKEUP_NORMAL (1 << 6) | ||
235 | #define PMECR_WKEVT_MASK (0xf << 2) | ||
236 | #define PMECR_WKEVT_SHIFT (2) | ||
237 | #define PMECR_WKEVT_GET(_v) (((_v) >> 2) & 0xf) | ||
238 | #define PMECR_WKEVT_ENERGY (0x1 << 2) | ||
239 | #define PMECR_WKEVT_LINK (0x2 << 2) | ||
240 | #define PMECR_WKEVT_MAGICPKT (0x4 << 2) | ||
241 | #define PMECR_WKEVT_FRAME (0x8 << 2) | ||
242 | #define PMECR_PM_MASK (0x3 << 0) | ||
243 | #define PMECR_PM_SHIFT (0) | ||
244 | #define PMECR_PM_NORMAL (0x0 << 0) | ||
245 | #define PMECR_PM_ENERGY (0x1 << 0) | ||
246 | #define PMECR_PM_SOFTDOWN (0x2 << 0) | ||
247 | #define PMECR_PM_POWERSAVE (0x3 << 0) | ||
248 | |||
249 | /* Standard MII PHY data */ | ||
250 | #define KS_P1MBCR 0xE4 | ||
251 | #define KS_P1MBSR 0xE6 | ||
252 | #define KS_PHY1ILR 0xE8 | ||
253 | #define KS_PHY1IHR 0xEA | ||
254 | #define KS_P1ANAR 0xEC | ||
255 | #define KS_P1ANLPR 0xEE | ||
256 | |||
257 | #define KS_P1SCLMD 0xF4 | ||
258 | #define P1SCLMD_LEDOFF (1 << 15) | ||
259 | #define P1SCLMD_TXIDS (1 << 14) | ||
260 | #define P1SCLMD_RESTARTAN (1 << 13) | ||
261 | #define P1SCLMD_DISAUTOMDIX (1 << 10) | ||
262 | #define P1SCLMD_FORCEMDIX (1 << 9) | ||
263 | #define P1SCLMD_AUTONEGEN (1 << 7) | ||
264 | #define P1SCLMD_FORCE100 (1 << 6) | ||
265 | #define P1SCLMD_FORCEFDX (1 << 5) | ||
266 | #define P1SCLMD_ADV_FLOW (1 << 4) | ||
267 | #define P1SCLMD_ADV_100BT_FDX (1 << 3) | ||
268 | #define P1SCLMD_ADV_100BT_HDX (1 << 2) | ||
269 | #define P1SCLMD_ADV_10BT_FDX (1 << 1) | ||
270 | #define P1SCLMD_ADV_10BT_HDX (1 << 0) | ||
271 | |||
272 | #define KS_P1CR 0xF6 | ||
273 | #define P1CR_HP_MDIX (1 << 15) | ||
274 | #define P1CR_REV_POL (1 << 13) | ||
275 | #define P1CR_OP_100M (1 << 10) | ||
276 | #define P1CR_OP_FDX (1 << 9) | ||
277 | #define P1CR_OP_MDI (1 << 7) | ||
278 | #define P1CR_AN_DONE (1 << 6) | ||
279 | #define P1CR_LINK_GOOD (1 << 5) | ||
280 | #define P1CR_PNTR_FLOW (1 << 4) | ||
281 | #define P1CR_PNTR_100BT_FDX (1 << 3) | ||
282 | #define P1CR_PNTR_100BT_HDX (1 << 2) | ||
283 | #define P1CR_PNTR_10BT_FDX (1 << 1) | ||
284 | #define P1CR_PNTR_10BT_HDX (1 << 0) | ||
285 | |||
286 | /* TX Frame control */ | ||
287 | |||
288 | #define TXFR_TXIC (1 << 15) | ||
289 | #define TXFR_TXFID_MASK (0x3f << 0) | ||
290 | #define TXFR_TXFID_SHIFT (0) | ||
291 | |||
292 | /* SPI frame opcodes */ | ||
293 | #define KS_SPIOP_RD (0x00) | ||
294 | #define KS_SPIOP_WR (0x40) | ||
295 | #define KS_SPIOP_RXFIFO (0x80) | ||
296 | #define KS_SPIOP_TXFIFO (0xC0) | ||
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index acd143da161d..61eabcac734c 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c | |||
@@ -179,7 +179,7 @@ static const struct net_device_ops macsonic_netdev_ops = { | |||
179 | .ndo_set_mac_address = eth_mac_addr, | 179 | .ndo_set_mac_address = eth_mac_addr, |
180 | }; | 180 | }; |
181 | 181 | ||
182 | static int __init macsonic_init(struct net_device *dev) | 182 | static int __devinit macsonic_init(struct net_device *dev) |
183 | { | 183 | { |
184 | struct sonic_local* lp = netdev_priv(dev); | 184 | struct sonic_local* lp = netdev_priv(dev); |
185 | 185 | ||
@@ -223,7 +223,7 @@ static int __init macsonic_init(struct net_device *dev) | |||
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev) | 226 | static int __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev) |
227 | { | 227 | { |
228 | struct sonic_local *lp = netdev_priv(dev); | 228 | struct sonic_local *lp = netdev_priv(dev); |
229 | const int prom_addr = ONBOARD_SONIC_PROM_BASE; | 229 | const int prom_addr = ONBOARD_SONIC_PROM_BASE; |
@@ -288,7 +288,7 @@ static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev) | |||
288 | } else return 0; | 288 | } else return 0; |
289 | } | 289 | } |
290 | 290 | ||
291 | static int __init mac_onboard_sonic_probe(struct net_device *dev) | 291 | static int __devinit mac_onboard_sonic_probe(struct net_device *dev) |
292 | { | 292 | { |
293 | /* Bwahahaha */ | 293 | /* Bwahahaha */ |
294 | static int once_is_more_than_enough; | 294 | static int once_is_more_than_enough; |
@@ -409,7 +409,7 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev) | |||
409 | return macsonic_init(dev); | 409 | return macsonic_init(dev); |
410 | } | 410 | } |
411 | 411 | ||
412 | static int __init mac_nubus_sonic_ethernet_addr(struct net_device *dev, | 412 | static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev, |
413 | unsigned long prom_addr, | 413 | unsigned long prom_addr, |
414 | int id) | 414 | int id) |
415 | { | 415 | { |
@@ -424,7 +424,7 @@ static int __init mac_nubus_sonic_ethernet_addr(struct net_device *dev, | |||
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
426 | 426 | ||
427 | static int __init macsonic_ident(struct nubus_dev *ndev) | 427 | static int __devinit macsonic_ident(struct nubus_dev *ndev) |
428 | { | 428 | { |
429 | if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC && | 429 | if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC && |
430 | ndev->dr_sw == NUBUS_DRSW_SONIC_LC) | 430 | ndev->dr_sw == NUBUS_DRSW_SONIC_LC) |
@@ -449,7 +449,7 @@ static int __init macsonic_ident(struct nubus_dev *ndev) | |||
449 | return -1; | 449 | return -1; |
450 | } | 450 | } |
451 | 451 | ||
452 | static int __init mac_nubus_sonic_probe(struct net_device *dev) | 452 | static int __devinit mac_nubus_sonic_probe(struct net_device *dev) |
453 | { | 453 | { |
454 | static int slots; | 454 | static int slots; |
455 | struct nubus_dev* ndev = NULL; | 455 | struct nubus_dev* ndev = NULL; |
@@ -562,7 +562,7 @@ static int __init mac_nubus_sonic_probe(struct net_device *dev) | |||
562 | return macsonic_init(dev); | 562 | return macsonic_init(dev); |
563 | } | 563 | } |
564 | 564 | ||
565 | static int __init mac_sonic_probe(struct platform_device *pdev) | 565 | static int __devinit mac_sonic_probe(struct platform_device *pdev) |
566 | { | 566 | { |
567 | struct net_device *dev; | 567 | struct net_device *dev; |
568 | struct sonic_local *lp; | 568 | struct sonic_local *lp; |
@@ -575,6 +575,7 @@ static int __init mac_sonic_probe(struct platform_device *pdev) | |||
575 | lp = netdev_priv(dev); | 575 | lp = netdev_priv(dev); |
576 | lp->device = &pdev->dev; | 576 | lp->device = &pdev->dev; |
577 | SET_NETDEV_DEV(dev, &pdev->dev); | 577 | SET_NETDEV_DEV(dev, &pdev->dev); |
578 | platform_set_drvdata(pdev, dev); | ||
578 | 579 | ||
579 | /* This will catch fatal stuff like -ENOMEM as well as success */ | 580 | /* This will catch fatal stuff like -ENOMEM as well as success */ |
580 | err = mac_onboard_sonic_probe(dev); | 581 | err = mac_onboard_sonic_probe(dev); |
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c index 091f99052c91..86467b444ac6 100644 --- a/drivers/net/mlx4/en_ethtool.c +++ b/drivers/net/mlx4/en_ethtool.c | |||
@@ -220,7 +220,7 @@ static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
220 | { | 220 | { |
221 | cmd->autoneg = AUTONEG_DISABLE; | 221 | cmd->autoneg = AUTONEG_DISABLE; |
222 | cmd->supported = SUPPORTED_10000baseT_Full; | 222 | cmd->supported = SUPPORTED_10000baseT_Full; |
223 | cmd->advertising = SUPPORTED_10000baseT_Full; | 223 | cmd->advertising = ADVERTISED_1000baseT_Full; |
224 | if (netif_carrier_ok(dev)) { | 224 | if (netif_carrier_ok(dev)) { |
225 | cmd->speed = SPEED_10000; | 225 | cmd->speed = SPEED_10000; |
226 | cmd->duplex = DUPLEX_FULL; | 226 | cmd->duplex = DUPLEX_FULL; |
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index e1cdba752e09..f86e05047d19 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h | |||
@@ -210,6 +210,7 @@ | |||
210 | #define NETXEN_CTX_SIGNATURE 0xdee0 | 210 | #define NETXEN_CTX_SIGNATURE 0xdee0 |
211 | #define NETXEN_CTX_SIGNATURE_V2 0x0002dee0 | 211 | #define NETXEN_CTX_SIGNATURE_V2 0x0002dee0 |
212 | #define NETXEN_CTX_RESET 0xbad0 | 212 | #define NETXEN_CTX_RESET 0xbad0 |
213 | #define NETXEN_CTX_D3_RESET 0xacc0 | ||
213 | #define NETXEN_RCV_PRODUCER(ringid) (ringid) | 214 | #define NETXEN_RCV_PRODUCER(ringid) (ringid) |
214 | 215 | ||
215 | #define PHAN_PEG_RCV_INITIALIZED 0xff01 | 216 | #define PHAN_PEG_RCV_INITIALIZED 0xff01 |
@@ -773,6 +774,8 @@ struct nx_host_tx_ring { | |||
773 | u32 crb_cmd_consumer; | 774 | u32 crb_cmd_consumer; |
774 | u32 num_desc; | 775 | u32 num_desc; |
775 | 776 | ||
777 | struct netdev_queue *txq; | ||
778 | |||
776 | struct netxen_cmd_buffer *cmd_buf_arr; | 779 | struct netxen_cmd_buffer *cmd_buf_arr; |
777 | struct cmd_desc_type0 *desc_head; | 780 | struct cmd_desc_type0 *desc_head; |
778 | dma_addr_t phys_addr; | 781 | dma_addr_t phys_addr; |
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 4754f5cffad0..9f8ae4719e2f 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c | |||
@@ -684,10 +684,8 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) | |||
684 | goto err_out_free; | 684 | goto err_out_free; |
685 | } else { | 685 | } else { |
686 | err = netxen_init_old_ctx(adapter); | 686 | err = netxen_init_old_ctx(adapter); |
687 | if (err) { | 687 | if (err) |
688 | netxen_free_hw_resources(adapter); | 688 | goto err_out_free; |
689 | return err; | ||
690 | } | ||
691 | } | 689 | } |
692 | 690 | ||
693 | return 0; | 691 | return 0; |
@@ -708,15 +706,18 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) | |||
708 | int port = adapter->portnum; | 706 | int port = adapter->portnum; |
709 | 707 | ||
710 | if (adapter->fw_major >= 4) { | 708 | if (adapter->fw_major >= 4) { |
711 | nx_fw_cmd_destroy_tx_ctx(adapter); | ||
712 | nx_fw_cmd_destroy_rx_ctx(adapter); | 709 | nx_fw_cmd_destroy_rx_ctx(adapter); |
710 | nx_fw_cmd_destroy_tx_ctx(adapter); | ||
713 | } else { | 711 | } else { |
714 | netxen_api_lock(adapter); | 712 | netxen_api_lock(adapter); |
715 | NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), | 713 | NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), |
716 | NETXEN_CTX_RESET | port); | 714 | NETXEN_CTX_D3_RESET | port); |
717 | netxen_api_unlock(adapter); | 715 | netxen_api_unlock(adapter); |
718 | } | 716 | } |
719 | 717 | ||
718 | /* Allow dma queues to drain after context reset */ | ||
719 | msleep(20); | ||
720 | |||
720 | recv_ctx = &adapter->recv_ctx; | 721 | recv_ctx = &adapter->recv_ctx; |
721 | 722 | ||
722 | if (recv_ctx->hwctx != NULL) { | 723 | if (recv_ctx->hwctx != NULL) { |
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index ce3b89d2cbb6..b9123d445c96 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c | |||
@@ -461,13 +461,14 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, | |||
461 | i = 0; | 461 | i = 0; |
462 | 462 | ||
463 | tx_ring = adapter->tx_ring; | 463 | tx_ring = adapter->tx_ring; |
464 | netif_tx_lock_bh(adapter->netdev); | 464 | __netif_tx_lock_bh(tx_ring->txq); |
465 | 465 | ||
466 | producer = tx_ring->producer; | 466 | producer = tx_ring->producer; |
467 | consumer = tx_ring->sw_consumer; | 467 | consumer = tx_ring->sw_consumer; |
468 | 468 | ||
469 | if (nr_desc >= find_diff_among(producer, consumer, tx_ring->num_desc)) { | 469 | if (nr_desc >= netxen_tx_avail(tx_ring)) { |
470 | netif_tx_unlock_bh(adapter->netdev); | 470 | netif_tx_stop_queue(tx_ring->txq); |
471 | __netif_tx_unlock_bh(tx_ring->txq); | ||
471 | return -EBUSY; | 472 | return -EBUSY; |
472 | } | 473 | } |
473 | 474 | ||
@@ -490,7 +491,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, | |||
490 | 491 | ||
491 | netxen_nic_update_cmd_producer(adapter, tx_ring); | 492 | netxen_nic_update_cmd_producer(adapter, tx_ring); |
492 | 493 | ||
493 | netif_tx_unlock_bh(adapter->netdev); | 494 | __netif_tx_unlock_bh(tx_ring->txq); |
494 | 495 | ||
495 | return 0; | 496 | return 0; |
496 | } | 497 | } |
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index b899bd51fcd8..5d3343ef3d86 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c | |||
@@ -214,6 +214,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) | |||
214 | adapter->tx_ring = tx_ring; | 214 | adapter->tx_ring = tx_ring; |
215 | 215 | ||
216 | tx_ring->num_desc = adapter->num_txd; | 216 | tx_ring->num_desc = adapter->num_txd; |
217 | tx_ring->txq = netdev_get_tx_queue(netdev, 0); | ||
217 | 218 | ||
218 | cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring)); | 219 | cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring)); |
219 | if (cmd_buf_arr == NULL) { | 220 | if (cmd_buf_arr == NULL) { |
@@ -1400,10 +1401,10 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) | |||
1400 | smp_mb(); | 1401 | smp_mb(); |
1401 | 1402 | ||
1402 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { | 1403 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { |
1403 | netif_tx_lock(netdev); | 1404 | __netif_tx_lock(tx_ring->txq, smp_processor_id()); |
1404 | if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) | 1405 | if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) |
1405 | netif_wake_queue(netdev); | 1406 | netif_wake_queue(netdev); |
1406 | netif_tx_unlock(netdev); | 1407 | __netif_tx_unlock(tx_ring->txq); |
1407 | } | 1408 | } |
1408 | } | 1409 | } |
1409 | /* | 1410 | /* |
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 27539ddf94c4..637ac8b89bac 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -215,9 +215,9 @@ netxen_napi_disable(struct netxen_adapter *adapter) | |||
215 | 215 | ||
216 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 216 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
217 | sds_ring = &recv_ctx->sds_rings[ring]; | 217 | sds_ring = &recv_ctx->sds_rings[ring]; |
218 | napi_disable(&sds_ring->napi); | ||
219 | netxen_nic_disable_int(sds_ring); | 218 | netxen_nic_disable_int(sds_ring); |
220 | synchronize_irq(sds_ring->irq); | 219 | napi_synchronize(&sds_ring->napi); |
220 | napi_disable(&sds_ring->napi); | ||
221 | } | 221 | } |
222 | } | 222 | } |
223 | 223 | ||
@@ -833,11 +833,11 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) | |||
833 | 833 | ||
834 | adapter->ahw.linkup = 0; | 834 | adapter->ahw.linkup = 0; |
835 | 835 | ||
836 | netxen_napi_enable(adapter); | ||
837 | |||
838 | if (adapter->max_sds_rings > 1) | 836 | if (adapter->max_sds_rings > 1) |
839 | netxen_config_rss(adapter, 1); | 837 | netxen_config_rss(adapter, 1); |
840 | 838 | ||
839 | netxen_napi_enable(adapter); | ||
840 | |||
841 | if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION) | 841 | if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION) |
842 | netxen_linkevent_request(adapter, 1); | 842 | netxen_linkevent_request(adapter, 1); |
843 | else | 843 | else |
@@ -851,8 +851,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) | |||
851 | static void | 851 | static void |
852 | netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) | 852 | netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) |
853 | { | 853 | { |
854 | spin_lock(&adapter->tx_clean_lock); | ||
854 | netif_carrier_off(netdev); | 855 | netif_carrier_off(netdev); |
855 | netif_stop_queue(netdev); | 856 | netif_tx_disable(netdev); |
856 | 857 | ||
857 | if (adapter->stop_port) | 858 | if (adapter->stop_port) |
858 | adapter->stop_port(adapter); | 859 | adapter->stop_port(adapter); |
@@ -863,9 +864,10 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) | |||
863 | netxen_napi_disable(adapter); | 864 | netxen_napi_disable(adapter); |
864 | 865 | ||
865 | netxen_release_tx_buffers(adapter); | 866 | netxen_release_tx_buffers(adapter); |
867 | spin_unlock(&adapter->tx_clean_lock); | ||
866 | 868 | ||
867 | FLUSH_SCHEDULED_WORK(); | ||
868 | del_timer_sync(&adapter->watchdog_timer); | 869 | del_timer_sync(&adapter->watchdog_timer); |
870 | FLUSH_SCHEDULED_WORK(); | ||
869 | } | 871 | } |
870 | 872 | ||
871 | 873 | ||
@@ -943,8 +945,8 @@ err_out_free_sw: | |||
943 | static void | 945 | static void |
944 | netxen_nic_detach(struct netxen_adapter *adapter) | 946 | netxen_nic_detach(struct netxen_adapter *adapter) |
945 | { | 947 | { |
946 | netxen_release_rx_buffers(adapter); | ||
947 | netxen_free_hw_resources(adapter); | 948 | netxen_free_hw_resources(adapter); |
949 | netxen_release_rx_buffers(adapter); | ||
948 | netxen_nic_free_irq(adapter); | 950 | netxen_nic_free_irq(adapter); |
949 | netxen_free_sw_resources(adapter); | 951 | netxen_free_sw_resources(adapter); |
950 | 952 | ||
@@ -1533,10 +1535,12 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) | |||
1533 | printk(KERN_ALERT | 1535 | printk(KERN_ALERT |
1534 | "%s: Device temperature %d degrees C exceeds" | 1536 | "%s: Device temperature %d degrees C exceeds" |
1535 | " maximum allowed. Hardware has been shut down.\n", | 1537 | " maximum allowed. Hardware has been shut down.\n", |
1536 | netxen_nic_driver_name, temp_val); | 1538 | netdev->name, temp_val); |
1539 | |||
1540 | netif_device_detach(netdev); | ||
1541 | netxen_nic_down(adapter, netdev); | ||
1542 | netxen_nic_detach(adapter); | ||
1537 | 1543 | ||
1538 | netif_carrier_off(netdev); | ||
1539 | netif_stop_queue(netdev); | ||
1540 | rv = 1; | 1544 | rv = 1; |
1541 | } else if (temp_state == NX_TEMP_WARN) { | 1545 | } else if (temp_state == NX_TEMP_WARN) { |
1542 | if (adapter->temp == NX_TEMP_NORMAL) { | 1546 | if (adapter->temp == NX_TEMP_NORMAL) { |
@@ -1544,13 +1548,13 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) | |||
1544 | "%s: Device temperature %d degrees C " | 1548 | "%s: Device temperature %d degrees C " |
1545 | "exceeds operating range." | 1549 | "exceeds operating range." |
1546 | " Immediate action needed.\n", | 1550 | " Immediate action needed.\n", |
1547 | netxen_nic_driver_name, temp_val); | 1551 | netdev->name, temp_val); |
1548 | } | 1552 | } |
1549 | } else { | 1553 | } else { |
1550 | if (adapter->temp == NX_TEMP_WARN) { | 1554 | if (adapter->temp == NX_TEMP_WARN) { |
1551 | printk(KERN_INFO | 1555 | printk(KERN_INFO |
1552 | "%s: Device temperature is now %d degrees C" | 1556 | "%s: Device temperature is now %d degrees C" |
1553 | " in normal range.\n", netxen_nic_driver_name, | 1557 | " in normal range.\n", netdev->name, |
1554 | temp_val); | 1558 | temp_val); |
1555 | } | 1559 | } |
1556 | } | 1560 | } |
@@ -1623,7 +1627,7 @@ void netxen_watchdog_task(struct work_struct *work) | |||
1623 | struct netxen_adapter *adapter = | 1627 | struct netxen_adapter *adapter = |
1624 | container_of(work, struct netxen_adapter, watchdog_task); | 1628 | container_of(work, struct netxen_adapter, watchdog_task); |
1625 | 1629 | ||
1626 | if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter)) | 1630 | if (netxen_nic_check_temp(adapter)) |
1627 | return; | 1631 | return; |
1628 | 1632 | ||
1629 | if (!adapter->has_link_events) | 1633 | if (!adapter->has_link_events) |
@@ -1645,6 +1649,9 @@ static void netxen_tx_timeout_task(struct work_struct *work) | |||
1645 | struct netxen_adapter *adapter = | 1649 | struct netxen_adapter *adapter = |
1646 | container_of(work, struct netxen_adapter, tx_timeout_task); | 1650 | container_of(work, struct netxen_adapter, tx_timeout_task); |
1647 | 1651 | ||
1652 | if (!netif_running(adapter->netdev)) | ||
1653 | return; | ||
1654 | |||
1648 | printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", | 1655 | printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", |
1649 | netxen_nic_driver_name, adapter->netdev->name); | 1656 | netxen_nic_driver_name, adapter->netdev->name); |
1650 | 1657 | ||
@@ -1757,7 +1764,8 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) | |||
1757 | 1764 | ||
1758 | if ((work_done < budget) && tx_complete) { | 1765 | if ((work_done < budget) && tx_complete) { |
1759 | napi_complete(&sds_ring->napi); | 1766 | napi_complete(&sds_ring->napi); |
1760 | netxen_nic_enable_int(sds_ring); | 1767 | if (netif_running(adapter->netdev)) |
1768 | netxen_nic_enable_int(sds_ring); | ||
1761 | } | 1769 | } |
1762 | 1770 | ||
1763 | return work_done; | 1771 | return work_done; |
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index ec7cf5ac4f05..690b9c76d34e 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c | |||
@@ -156,6 +156,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev); | |||
156 | static int el3_rx(struct net_device *dev); | 156 | static int el3_rx(struct net_device *dev); |
157 | static int el3_close(struct net_device *dev); | 157 | static int el3_close(struct net_device *dev); |
158 | static void el3_tx_timeout(struct net_device *dev); | 158 | static void el3_tx_timeout(struct net_device *dev); |
159 | static void set_rx_mode(struct net_device *dev); | ||
159 | static void set_multicast_list(struct net_device *dev); | 160 | static void set_multicast_list(struct net_device *dev); |
160 | static const struct ethtool_ops netdev_ethtool_ops; | 161 | static const struct ethtool_ops netdev_ethtool_ops; |
161 | 162 | ||
@@ -488,8 +489,7 @@ static void tc589_reset(struct net_device *dev) | |||
488 | /* Switch to register set 1 for normal use. */ | 489 | /* Switch to register set 1 for normal use. */ |
489 | EL3WINDOW(1); | 490 | EL3WINDOW(1); |
490 | 491 | ||
491 | /* Accept b-cast and phys addr only. */ | 492 | set_rx_mode(dev); |
492 | outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); | ||
493 | outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ | 493 | outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ |
494 | outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ | 494 | outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ |
495 | outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ | 495 | outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ |
@@ -700,7 +700,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id) | |||
700 | if (fifo_diag & 0x2000) { | 700 | if (fifo_diag & 0x2000) { |
701 | /* Rx underrun */ | 701 | /* Rx underrun */ |
702 | tc589_wait_for_completion(dev, RxReset); | 702 | tc589_wait_for_completion(dev, RxReset); |
703 | set_multicast_list(dev); | 703 | set_rx_mode(dev); |
704 | outw(RxEnable, ioaddr + EL3_CMD); | 704 | outw(RxEnable, ioaddr + EL3_CMD); |
705 | } | 705 | } |
706 | outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); | 706 | outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); |
@@ -905,14 +905,11 @@ static int el3_rx(struct net_device *dev) | |||
905 | return 0; | 905 | return 0; |
906 | } | 906 | } |
907 | 907 | ||
908 | static void set_multicast_list(struct net_device *dev) | 908 | static void set_rx_mode(struct net_device *dev) |
909 | { | 909 | { |
910 | struct el3_private *lp = netdev_priv(dev); | ||
911 | struct pcmcia_device *link = lp->p_dev; | ||
912 | unsigned int ioaddr = dev->base_addr; | 910 | unsigned int ioaddr = dev->base_addr; |
913 | u16 opts = SetRxFilter | RxStation | RxBroadcast; | 911 | u16 opts = SetRxFilter | RxStation | RxBroadcast; |
914 | 912 | ||
915 | if (!pcmcia_dev_present(link)) return; | ||
916 | if (dev->flags & IFF_PROMISC) | 913 | if (dev->flags & IFF_PROMISC) |
917 | opts |= RxMulticast | RxProm; | 914 | opts |= RxMulticast | RxProm; |
918 | else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) | 915 | else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) |
@@ -920,6 +917,16 @@ static void set_multicast_list(struct net_device *dev) | |||
920 | outw(opts, ioaddr + EL3_CMD); | 917 | outw(opts, ioaddr + EL3_CMD); |
921 | } | 918 | } |
922 | 919 | ||
920 | static void set_multicast_list(struct net_device *dev) | ||
921 | { | ||
922 | struct el3_private *priv = netdev_priv(dev); | ||
923 | unsigned long flags; | ||
924 | |||
925 | spin_lock_irqsave(&priv->lock, flags); | ||
926 | set_rx_mode(dev); | ||
927 | spin_unlock_irqrestore(&priv->lock, flags); | ||
928 | } | ||
929 | |||
923 | static int el3_close(struct net_device *dev) | 930 | static int el3_close(struct net_device *dev) |
924 | { | 931 | { |
925 | struct el3_private *lp = netdev_priv(dev); | 932 | struct el3_private *lp = netdev_priv(dev); |
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 18821f217e19..e3156c97bb58 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c | |||
@@ -1593,6 +1593,7 @@ out: | |||
1593 | static struct pci_device_id sc92031_pci_device_id_table[] __devinitdata = { | 1593 | static struct pci_device_id sc92031_pci_device_id_table[] __devinitdata = { |
1594 | { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) }, | 1594 | { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) }, |
1595 | { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) }, | 1595 | { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) }, |
1596 | { PCI_DEVICE(0x1088, 0x2031) }, | ||
1596 | { 0, } | 1597 | { 0, } |
1597 | }; | 1598 | }; |
1598 | MODULE_DEVICE_TABLE(pci, sc92031_pci_device_id_table); | 1599 | MODULE_DEVICE_TABLE(pci, sc92031_pci_device_id_table); |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index daf961ab68bc..3550c5dcd93c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -1151,14 +1151,7 @@ stopped: | |||
1151 | 1151 | ||
1152 | /* reset the Rx prefetch unit */ | 1152 | /* reset the Rx prefetch unit */ |
1153 | sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); | 1153 | sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); |
1154 | 1154 | mmiowb(); | |
1155 | /* Reset the RAM Buffer receive queue */ | ||
1156 | sky2_write8(hw, RB_ADDR(rxq, RB_CTRL), RB_RST_SET); | ||
1157 | |||
1158 | /* Reset Rx MAC FIFO */ | ||
1159 | sky2_write8(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), GMF_RST_SET); | ||
1160 | |||
1161 | sky2_read8(hw, B0_CTST); | ||
1162 | } | 1155 | } |
1163 | 1156 | ||
1164 | /* Clean out receive buffer area, assumes receiver hardware stopped */ | 1157 | /* Clean out receive buffer area, assumes receiver hardware stopped */ |
@@ -1825,12 +1818,6 @@ static int sky2_down(struct net_device *dev) | |||
1825 | if (netif_msg_ifdown(sky2)) | 1818 | if (netif_msg_ifdown(sky2)) |
1826 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); | 1819 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); |
1827 | 1820 | ||
1828 | /* Disable port IRQ */ | ||
1829 | imask = sky2_read32(hw, B0_IMSK); | ||
1830 | imask &= ~portirq_msk[port]; | ||
1831 | sky2_write32(hw, B0_IMSK, imask); | ||
1832 | sky2_read32(hw, B0_IMSK); | ||
1833 | |||
1834 | /* Force flow control off */ | 1821 | /* Force flow control off */ |
1835 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); | 1822 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); |
1836 | 1823 | ||
@@ -1870,8 +1857,6 @@ static int sky2_down(struct net_device *dev) | |||
1870 | 1857 | ||
1871 | sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET); | 1858 | sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET); |
1872 | 1859 | ||
1873 | sky2_rx_stop(sky2); | ||
1874 | |||
1875 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); | 1860 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); |
1876 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); | 1861 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); |
1877 | 1862 | ||
@@ -1881,6 +1866,14 @@ static int sky2_down(struct net_device *dev) | |||
1881 | sky2_write32(hw, STAT_ISR_TIMER_CNT, 0); | 1866 | sky2_write32(hw, STAT_ISR_TIMER_CNT, 0); |
1882 | sky2_read8(hw, STAT_ISR_TIMER_CTRL); | 1867 | sky2_read8(hw, STAT_ISR_TIMER_CTRL); |
1883 | 1868 | ||
1869 | sky2_rx_stop(sky2); | ||
1870 | |||
1871 | /* Disable port IRQ */ | ||
1872 | imask = sky2_read32(hw, B0_IMSK); | ||
1873 | imask &= ~portirq_msk[port]; | ||
1874 | sky2_write32(hw, B0_IMSK, imask); | ||
1875 | sky2_read32(hw, B0_IMSK); | ||
1876 | |||
1884 | synchronize_irq(hw->pdev->irq); | 1877 | synchronize_irq(hw->pdev->irq); |
1885 | napi_synchronize(&hw->napi); | 1878 | napi_synchronize(&hw->napi); |
1886 | 1879 | ||
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index a906d3998131..c47237c2d638 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
@@ -369,4 +369,12 @@ config USB_NET_INT51X1 | |||
369 | (Powerline Communications) solution with an Intellon | 369 | (Powerline Communications) solution with an Intellon |
370 | INT51x1/INT5200 chip, like the "devolo dLan duo". | 370 | INT51x1/INT5200 chip, like the "devolo dLan duo". |
371 | 371 | ||
372 | config USB_CDC_PHONET | ||
373 | tristate "CDC Phonet support" | ||
374 | depends on PHONET | ||
375 | help | ||
376 | Choose this option to support the Phonet interface to a Nokia | ||
377 | cellular modem, as found on most Nokia handsets with the | ||
378 | "PC suite" USB profile. | ||
379 | |||
372 | endmenu | 380 | endmenu |
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index b870b0b1cbe0..e17afb78f372 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile | |||
@@ -21,4 +21,5 @@ obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o | |||
21 | obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o | 21 | obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o |
22 | obj-$(CONFIG_USB_USBNET) += usbnet.o | 22 | obj-$(CONFIG_USB_USBNET) += usbnet.o |
23 | obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o | 23 | obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o |
24 | obj-$(CONFIG_USB_CDC_PHONET) += cdc-phonet.o | ||
24 | 25 | ||
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c new file mode 100644 index 000000000000..792af72da8ac --- /dev/null +++ b/drivers/net/usb/cdc-phonet.c | |||
@@ -0,0 +1,461 @@ | |||
1 | /* | ||
2 | * phonet.c -- USB CDC Phonet host driver | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Nokia Corporation. All rights reserved. | ||
5 | * | ||
6 | * Author: Rémi Denis-Courmont | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/usb/cdc.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/if_arp.h> | ||
29 | #include <linux/if_phonet.h> | ||
30 | |||
31 | #define PN_MEDIA_USB 0x1B | ||
32 | |||
33 | static const unsigned rxq_size = 17; | ||
34 | |||
35 | struct usbpn_dev { | ||
36 | struct net_device *dev; | ||
37 | |||
38 | struct usb_interface *intf, *data_intf; | ||
39 | struct usb_device *usb; | ||
40 | unsigned int tx_pipe, rx_pipe; | ||
41 | u8 active_setting; | ||
42 | u8 disconnected; | ||
43 | |||
44 | unsigned tx_queue; | ||
45 | spinlock_t tx_lock; | ||
46 | |||
47 | spinlock_t rx_lock; | ||
48 | struct sk_buff *rx_skb; | ||
49 | struct urb *urbs[0]; | ||
50 | }; | ||
51 | |||
52 | static void tx_complete(struct urb *req); | ||
53 | static void rx_complete(struct urb *req); | ||
54 | |||
55 | /* | ||
56 | * Network device callbacks | ||
57 | */ | ||
58 | static int usbpn_xmit(struct sk_buff *skb, struct net_device *dev) | ||
59 | { | ||
60 | struct usbpn_dev *pnd = netdev_priv(dev); | ||
61 | struct urb *req = NULL; | ||
62 | unsigned long flags; | ||
63 | int err; | ||
64 | |||
65 | if (skb->protocol != htons(ETH_P_PHONET)) | ||
66 | goto drop; | ||
67 | |||
68 | req = usb_alloc_urb(0, GFP_ATOMIC); | ||
69 | if (!req) | ||
70 | goto drop; | ||
71 | usb_fill_bulk_urb(req, pnd->usb, pnd->tx_pipe, skb->data, skb->len, | ||
72 | tx_complete, skb); | ||
73 | req->transfer_flags = URB_ZERO_PACKET; | ||
74 | err = usb_submit_urb(req, GFP_ATOMIC); | ||
75 | if (err) { | ||
76 | usb_free_urb(req); | ||
77 | goto drop; | ||
78 | } | ||
79 | |||
80 | spin_lock_irqsave(&pnd->tx_lock, flags); | ||
81 | pnd->tx_queue++; | ||
82 | if (pnd->tx_queue >= dev->tx_queue_len) | ||
83 | netif_stop_queue(dev); | ||
84 | spin_unlock_irqrestore(&pnd->tx_lock, flags); | ||
85 | return 0; | ||
86 | |||
87 | drop: | ||
88 | dev_kfree_skb(skb); | ||
89 | dev->stats.tx_dropped++; | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static void tx_complete(struct urb *req) | ||
94 | { | ||
95 | struct sk_buff *skb = req->context; | ||
96 | struct net_device *dev = skb->dev; | ||
97 | struct usbpn_dev *pnd = netdev_priv(dev); | ||
98 | |||
99 | switch (req->status) { | ||
100 | case 0: | ||
101 | dev->stats.tx_bytes += skb->len; | ||
102 | break; | ||
103 | |||
104 | case -ENOENT: | ||
105 | case -ECONNRESET: | ||
106 | case -ESHUTDOWN: | ||
107 | dev->stats.tx_aborted_errors++; | ||
108 | default: | ||
109 | dev->stats.tx_errors++; | ||
110 | dev_dbg(&dev->dev, "TX error (%d)\n", req->status); | ||
111 | } | ||
112 | dev->stats.tx_packets++; | ||
113 | |||
114 | spin_lock(&pnd->tx_lock); | ||
115 | pnd->tx_queue--; | ||
116 | netif_wake_queue(dev); | ||
117 | spin_unlock(&pnd->tx_lock); | ||
118 | |||
119 | dev_kfree_skb_any(skb); | ||
120 | usb_free_urb(req); | ||
121 | } | ||
122 | |||
123 | static int rx_submit(struct usbpn_dev *pnd, struct urb *req, gfp_t gfp_flags) | ||
124 | { | ||
125 | struct net_device *dev = pnd->dev; | ||
126 | struct page *page; | ||
127 | int err; | ||
128 | |||
129 | page = __netdev_alloc_page(dev, gfp_flags); | ||
130 | if (!page) | ||
131 | return -ENOMEM; | ||
132 | |||
133 | usb_fill_bulk_urb(req, pnd->usb, pnd->rx_pipe, page_address(page), | ||
134 | PAGE_SIZE, rx_complete, dev); | ||
135 | req->transfer_flags = 0; | ||
136 | err = usb_submit_urb(req, gfp_flags); | ||
137 | if (unlikely(err)) { | ||
138 | dev_dbg(&dev->dev, "RX submit error (%d)\n", err); | ||
139 | netdev_free_page(dev, page); | ||
140 | } | ||
141 | return err; | ||
142 | } | ||
143 | |||
144 | static void rx_complete(struct urb *req) | ||
145 | { | ||
146 | struct net_device *dev = req->context; | ||
147 | struct usbpn_dev *pnd = netdev_priv(dev); | ||
148 | struct page *page = virt_to_page(req->transfer_buffer); | ||
149 | struct sk_buff *skb; | ||
150 | unsigned long flags; | ||
151 | |||
152 | switch (req->status) { | ||
153 | case 0: | ||
154 | spin_lock_irqsave(&pnd->rx_lock, flags); | ||
155 | skb = pnd->rx_skb; | ||
156 | if (!skb) { | ||
157 | skb = pnd->rx_skb = netdev_alloc_skb(dev, 12); | ||
158 | if (likely(skb)) { | ||
159 | /* Can't use pskb_pull() on page in IRQ */ | ||
160 | memcpy(skb_put(skb, 1), page_address(page), 1); | ||
161 | skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, | ||
162 | page, 1, req->actual_length); | ||
163 | page = NULL; | ||
164 | } | ||
165 | } else { | ||
166 | skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, | ||
167 | page, 0, req->actual_length); | ||
168 | page = NULL; | ||
169 | } | ||
170 | if (req->actual_length < PAGE_SIZE) | ||
171 | pnd->rx_skb = NULL; /* Last fragment */ | ||
172 | else | ||
173 | skb = NULL; | ||
174 | spin_unlock_irqrestore(&pnd->rx_lock, flags); | ||
175 | if (skb) { | ||
176 | skb->protocol = htons(ETH_P_PHONET); | ||
177 | skb_reset_mac_header(skb); | ||
178 | __skb_pull(skb, 1); | ||
179 | skb->dev = dev; | ||
180 | dev->stats.rx_packets++; | ||
181 | dev->stats.rx_bytes += skb->len; | ||
182 | |||
183 | netif_rx(skb); | ||
184 | } | ||
185 | goto resubmit; | ||
186 | |||
187 | case -ENOENT: | ||
188 | case -ECONNRESET: | ||
189 | case -ESHUTDOWN: | ||
190 | req = NULL; | ||
191 | break; | ||
192 | |||
193 | case -EOVERFLOW: | ||
194 | dev->stats.rx_over_errors++; | ||
195 | dev_dbg(&dev->dev, "RX overflow\n"); | ||
196 | break; | ||
197 | |||
198 | case -EILSEQ: | ||
199 | dev->stats.rx_crc_errors++; | ||
200 | break; | ||
201 | } | ||
202 | |||
203 | dev->stats.rx_errors++; | ||
204 | resubmit: | ||
205 | if (page) | ||
206 | netdev_free_page(dev, page); | ||
207 | if (req) | ||
208 | rx_submit(pnd, req, GFP_ATOMIC); | ||
209 | } | ||
210 | |||
211 | static int usbpn_close(struct net_device *dev); | ||
212 | |||
213 | static int usbpn_open(struct net_device *dev) | ||
214 | { | ||
215 | struct usbpn_dev *pnd = netdev_priv(dev); | ||
216 | int err; | ||
217 | unsigned i; | ||
218 | unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber; | ||
219 | |||
220 | err = usb_set_interface(pnd->usb, num, pnd->active_setting); | ||
221 | if (err) | ||
222 | return err; | ||
223 | |||
224 | for (i = 0; i < rxq_size; i++) { | ||
225 | struct urb *req = usb_alloc_urb(0, GFP_KERNEL); | ||
226 | |||
227 | if (!req || rx_submit(pnd, req, GFP_KERNEL)) { | ||
228 | usbpn_close(dev); | ||
229 | return -ENOMEM; | ||
230 | } | ||
231 | pnd->urbs[i] = req; | ||
232 | } | ||
233 | |||
234 | netif_wake_queue(dev); | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int usbpn_close(struct net_device *dev) | ||
239 | { | ||
240 | struct usbpn_dev *pnd = netdev_priv(dev); | ||
241 | unsigned i; | ||
242 | unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber; | ||
243 | |||
244 | netif_stop_queue(dev); | ||
245 | |||
246 | for (i = 0; i < rxq_size; i++) { | ||
247 | struct urb *req = pnd->urbs[i]; | ||
248 | |||
249 | if (!req) | ||
250 | continue; | ||
251 | usb_kill_urb(req); | ||
252 | usb_free_urb(req); | ||
253 | pnd->urbs[i] = NULL; | ||
254 | } | ||
255 | |||
256 | return usb_set_interface(pnd->usb, num, !pnd->active_setting); | ||
257 | } | ||
258 | |||
259 | static int usbpn_set_mtu(struct net_device *dev, int new_mtu) | ||
260 | { | ||
261 | if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU)) | ||
262 | return -EINVAL; | ||
263 | |||
264 | dev->mtu = new_mtu; | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static const struct net_device_ops usbpn_ops = { | ||
269 | .ndo_open = usbpn_open, | ||
270 | .ndo_stop = usbpn_close, | ||
271 | .ndo_start_xmit = usbpn_xmit, | ||
272 | .ndo_change_mtu = usbpn_set_mtu, | ||
273 | }; | ||
274 | |||
275 | static void usbpn_setup(struct net_device *dev) | ||
276 | { | ||
277 | dev->features = 0; | ||
278 | dev->netdev_ops = &usbpn_ops, | ||
279 | dev->header_ops = &phonet_header_ops; | ||
280 | dev->type = ARPHRD_PHONET; | ||
281 | dev->flags = IFF_POINTOPOINT | IFF_NOARP; | ||
282 | dev->mtu = PHONET_MAX_MTU; | ||
283 | dev->hard_header_len = 1; | ||
284 | dev->dev_addr[0] = PN_MEDIA_USB; | ||
285 | dev->addr_len = 1; | ||
286 | dev->tx_queue_len = 3; | ||
287 | |||
288 | dev->destructor = free_netdev; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * USB driver callbacks | ||
293 | */ | ||
294 | static struct usb_device_id usbpn_ids[] = { | ||
295 | { | ||
296 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | ||
297 | | USB_DEVICE_ID_MATCH_INT_CLASS | ||
298 | | USB_DEVICE_ID_MATCH_INT_SUBCLASS, | ||
299 | .idVendor = 0x0421, /* Nokia */ | ||
300 | .bInterfaceClass = USB_CLASS_COMM, | ||
301 | .bInterfaceSubClass = 0xFE, | ||
302 | }, | ||
303 | { }, | ||
304 | }; | ||
305 | |||
306 | MODULE_DEVICE_TABLE(usb, usbpn_ids); | ||
307 | |||
308 | static struct usb_driver usbpn_driver; | ||
309 | |||
310 | int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
311 | { | ||
312 | static const char ifname[] = "usbpn%d"; | ||
313 | const struct usb_cdc_union_desc *union_header = NULL; | ||
314 | const struct usb_cdc_header_desc *phonet_header = NULL; | ||
315 | const struct usb_host_interface *data_desc; | ||
316 | struct usb_interface *data_intf; | ||
317 | struct usb_device *usbdev = interface_to_usbdev(intf); | ||
318 | struct net_device *dev; | ||
319 | struct usbpn_dev *pnd; | ||
320 | u8 *data; | ||
321 | int len, err; | ||
322 | |||
323 | data = intf->altsetting->extra; | ||
324 | len = intf->altsetting->extralen; | ||
325 | while (len >= 3) { | ||
326 | u8 dlen = data[0]; | ||
327 | if (dlen < 3) | ||
328 | return -EINVAL; | ||
329 | |||
330 | /* bDescriptorType */ | ||
331 | if (data[1] == USB_DT_CS_INTERFACE) { | ||
332 | /* bDescriptorSubType */ | ||
333 | switch (data[2]) { | ||
334 | case USB_CDC_UNION_TYPE: | ||
335 | if (union_header || dlen < 5) | ||
336 | break; | ||
337 | union_header = | ||
338 | (struct usb_cdc_union_desc *)data; | ||
339 | break; | ||
340 | case 0xAB: | ||
341 | if (phonet_header || dlen < 5) | ||
342 | break; | ||
343 | phonet_header = | ||
344 | (struct usb_cdc_header_desc *)data; | ||
345 | break; | ||
346 | } | ||
347 | } | ||
348 | data += dlen; | ||
349 | len -= dlen; | ||
350 | } | ||
351 | |||
352 | if (!union_header || !phonet_header) | ||
353 | return -EINVAL; | ||
354 | |||
355 | data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0); | ||
356 | if (data_intf == NULL) | ||
357 | return -ENODEV; | ||
358 | /* Data interface has one inactive and one active setting */ | ||
359 | if (data_intf->num_altsetting != 2) | ||
360 | return -EINVAL; | ||
361 | if (data_intf->altsetting[0].desc.bNumEndpoints == 0 | ||
362 | && data_intf->altsetting[1].desc.bNumEndpoints == 2) | ||
363 | data_desc = data_intf->altsetting + 1; | ||
364 | else | ||
365 | if (data_intf->altsetting[0].desc.bNumEndpoints == 2 | ||
366 | && data_intf->altsetting[1].desc.bNumEndpoints == 0) | ||
367 | data_desc = data_intf->altsetting; | ||
368 | else | ||
369 | return -EINVAL; | ||
370 | |||
371 | dev = alloc_netdev(sizeof(*pnd) + sizeof(pnd->urbs[0]) * rxq_size, | ||
372 | ifname, usbpn_setup); | ||
373 | if (!dev) | ||
374 | return -ENOMEM; | ||
375 | |||
376 | pnd = netdev_priv(dev); | ||
377 | SET_NETDEV_DEV(dev, &intf->dev); | ||
378 | netif_stop_queue(dev); | ||
379 | |||
380 | pnd->dev = dev; | ||
381 | pnd->usb = usb_get_dev(usbdev); | ||
382 | pnd->intf = intf; | ||
383 | pnd->data_intf = data_intf; | ||
384 | spin_lock_init(&pnd->tx_lock); | ||
385 | spin_lock_init(&pnd->rx_lock); | ||
386 | /* Endpoints */ | ||
387 | if (usb_pipein(data_desc->endpoint[0].desc.bEndpointAddress)) { | ||
388 | pnd->rx_pipe = usb_rcvbulkpipe(usbdev, | ||
389 | data_desc->endpoint[0].desc.bEndpointAddress); | ||
390 | pnd->tx_pipe = usb_sndbulkpipe(usbdev, | ||
391 | data_desc->endpoint[1].desc.bEndpointAddress); | ||
392 | } else { | ||
393 | pnd->rx_pipe = usb_rcvbulkpipe(usbdev, | ||
394 | data_desc->endpoint[1].desc.bEndpointAddress); | ||
395 | pnd->tx_pipe = usb_sndbulkpipe(usbdev, | ||
396 | data_desc->endpoint[0].desc.bEndpointAddress); | ||
397 | } | ||
398 | pnd->active_setting = data_desc - data_intf->altsetting; | ||
399 | |||
400 | err = usb_driver_claim_interface(&usbpn_driver, data_intf, pnd); | ||
401 | if (err) | ||
402 | goto out; | ||
403 | |||
404 | /* Force inactive mode until the network device is brought UP */ | ||
405 | usb_set_interface(usbdev, union_header->bSlaveInterface0, | ||
406 | !pnd->active_setting); | ||
407 | usb_set_intfdata(intf, pnd); | ||
408 | |||
409 | err = register_netdev(dev); | ||
410 | if (err) { | ||
411 | usb_driver_release_interface(&usbpn_driver, data_intf); | ||
412 | goto out; | ||
413 | } | ||
414 | |||
415 | dev_dbg(&dev->dev, "USB CDC Phonet device found\n"); | ||
416 | return 0; | ||
417 | |||
418 | out: | ||
419 | usb_set_intfdata(intf, NULL); | ||
420 | free_netdev(dev); | ||
421 | return err; | ||
422 | } | ||
423 | |||
424 | static void usbpn_disconnect(struct usb_interface *intf) | ||
425 | { | ||
426 | struct usbpn_dev *pnd = usb_get_intfdata(intf); | ||
427 | struct usb_device *usb = pnd->usb; | ||
428 | |||
429 | if (pnd->disconnected) | ||
430 | return; | ||
431 | |||
432 | pnd->disconnected = 1; | ||
433 | usb_driver_release_interface(&usbpn_driver, | ||
434 | (pnd->intf == intf) ? pnd->data_intf : pnd->intf); | ||
435 | unregister_netdev(pnd->dev); | ||
436 | usb_put_dev(usb); | ||
437 | } | ||
438 | |||
439 | static struct usb_driver usbpn_driver = { | ||
440 | .name = "cdc_phonet", | ||
441 | .probe = usbpn_probe, | ||
442 | .disconnect = usbpn_disconnect, | ||
443 | .id_table = usbpn_ids, | ||
444 | }; | ||
445 | |||
446 | static int __init usbpn_init(void) | ||
447 | { | ||
448 | return usb_register(&usbpn_driver); | ||
449 | } | ||
450 | |||
451 | static void __exit usbpn_exit(void) | ||
452 | { | ||
453 | usb_deregister(&usbpn_driver); | ||
454 | } | ||
455 | |||
456 | module_init(usbpn_init); | ||
457 | module_exit(usbpn_exit); | ||
458 | |||
459 | MODULE_AUTHOR("Remi Denis-Courmont"); | ||
460 | MODULE_DESCRIPTION("USB CDC Phonet host interface"); | ||
461 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index cd35d50e46d4..45cebfb302cf 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c | |||
@@ -311,7 +311,7 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
311 | * bmCRC = 0 : CRC = 0xDEADBEEF | 311 | * bmCRC = 0 : CRC = 0xDEADBEEF |
312 | */ | 312 | */ |
313 | if (header & BIT(14)) | 313 | if (header & BIT(14)) |
314 | crc2 = ~crc32_le(~0, skb2->data, len); | 314 | crc2 = ~crc32_le(~0, skb2->data, skb2->len); |
315 | else | 315 | else |
316 | crc2 = 0xdeadbeef; | 316 | crc2 = 0xdeadbeef; |
317 | 317 | ||
diff --git a/include/net/sock.h b/include/net/sock.h index 2c0da9239b95..950409dcec3d 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -104,15 +104,15 @@ struct net; | |||
104 | 104 | ||
105 | /** | 105 | /** |
106 | * struct sock_common - minimal network layer representation of sockets | 106 | * struct sock_common - minimal network layer representation of sockets |
107 | * @skc_node: main hash linkage for various protocol lookup tables | ||
108 | * @skc_nulls_node: main hash linkage for UDP/UDP-Lite protocol | ||
109 | * @skc_refcnt: reference count | ||
110 | * @skc_hash: hash value used with various protocol lookup tables | ||
107 | * @skc_family: network address family | 111 | * @skc_family: network address family |
108 | * @skc_state: Connection state | 112 | * @skc_state: Connection state |
109 | * @skc_reuse: %SO_REUSEADDR setting | 113 | * @skc_reuse: %SO_REUSEADDR setting |
110 | * @skc_bound_dev_if: bound device index if != 0 | 114 | * @skc_bound_dev_if: bound device index if != 0 |
111 | * @skc_node: main hash linkage for various protocol lookup tables | ||
112 | * @skc_nulls_node: main hash linkage for UDP/UDP-Lite protocol | ||
113 | * @skc_bind_node: bind hash linkage for various protocol lookup tables | 115 | * @skc_bind_node: bind hash linkage for various protocol lookup tables |
114 | * @skc_refcnt: reference count | ||
115 | * @skc_hash: hash value used with various protocol lookup tables | ||
116 | * @skc_prot: protocol handlers inside a network family | 116 | * @skc_prot: protocol handlers inside a network family |
117 | * @skc_net: reference to the network namespace of this socket | 117 | * @skc_net: reference to the network namespace of this socket |
118 | * | 118 | * |
@@ -120,17 +120,21 @@ struct net; | |||
120 | * for struct sock and struct inet_timewait_sock. | 120 | * for struct sock and struct inet_timewait_sock. |
121 | */ | 121 | */ |
122 | struct sock_common { | 122 | struct sock_common { |
123 | unsigned short skc_family; | 123 | /* |
124 | volatile unsigned char skc_state; | 124 | * first fields are not copied in sock_copy() |
125 | unsigned char skc_reuse; | 125 | */ |
126 | int skc_bound_dev_if; | ||
127 | union { | 126 | union { |
128 | struct hlist_node skc_node; | 127 | struct hlist_node skc_node; |
129 | struct hlist_nulls_node skc_nulls_node; | 128 | struct hlist_nulls_node skc_nulls_node; |
130 | }; | 129 | }; |
131 | struct hlist_node skc_bind_node; | ||
132 | atomic_t skc_refcnt; | 130 | atomic_t skc_refcnt; |
131 | |||
133 | unsigned int skc_hash; | 132 | unsigned int skc_hash; |
133 | unsigned short skc_family; | ||
134 | volatile unsigned char skc_state; | ||
135 | unsigned char skc_reuse; | ||
136 | int skc_bound_dev_if; | ||
137 | struct hlist_node skc_bind_node; | ||
134 | struct proto *skc_prot; | 138 | struct proto *skc_prot; |
135 | #ifdef CONFIG_NET_NS | 139 | #ifdef CONFIG_NET_NS |
136 | struct net *skc_net; | 140 | struct net *skc_net; |
@@ -208,15 +212,17 @@ struct sock { | |||
208 | * don't add nothing before this first member (__sk_common) --acme | 212 | * don't add nothing before this first member (__sk_common) --acme |
209 | */ | 213 | */ |
210 | struct sock_common __sk_common; | 214 | struct sock_common __sk_common; |
215 | #define sk_node __sk_common.skc_node | ||
216 | #define sk_nulls_node __sk_common.skc_nulls_node | ||
217 | #define sk_refcnt __sk_common.skc_refcnt | ||
218 | |||
219 | #define sk_copy_start __sk_common.skc_hash | ||
220 | #define sk_hash __sk_common.skc_hash | ||
211 | #define sk_family __sk_common.skc_family | 221 | #define sk_family __sk_common.skc_family |
212 | #define sk_state __sk_common.skc_state | 222 | #define sk_state __sk_common.skc_state |
213 | #define sk_reuse __sk_common.skc_reuse | 223 | #define sk_reuse __sk_common.skc_reuse |
214 | #define sk_bound_dev_if __sk_common.skc_bound_dev_if | 224 | #define sk_bound_dev_if __sk_common.skc_bound_dev_if |
215 | #define sk_node __sk_common.skc_node | ||
216 | #define sk_nulls_node __sk_common.skc_nulls_node | ||
217 | #define sk_bind_node __sk_common.skc_bind_node | 225 | #define sk_bind_node __sk_common.skc_bind_node |
218 | #define sk_refcnt __sk_common.skc_refcnt | ||
219 | #define sk_hash __sk_common.skc_hash | ||
220 | #define sk_prot __sk_common.skc_prot | 226 | #define sk_prot __sk_common.skc_prot |
221 | #define sk_net __sk_common.skc_net | 227 | #define sk_net __sk_common.skc_net |
222 | kmemcheck_bitfield_begin(flags); | 228 | kmemcheck_bitfield_begin(flags); |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 19f4150f4d4d..88af84306471 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -1425,6 +1425,11 @@ struct tcp_request_sock_ops { | |||
1425 | #ifdef CONFIG_TCP_MD5SIG | 1425 | #ifdef CONFIG_TCP_MD5SIG |
1426 | struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk, | 1426 | struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk, |
1427 | struct request_sock *req); | 1427 | struct request_sock *req); |
1428 | int (*calc_md5_hash) (char *location, | ||
1429 | struct tcp_md5sig_key *md5, | ||
1430 | struct sock *sk, | ||
1431 | struct request_sock *req, | ||
1432 | struct sk_buff *skb); | ||
1428 | #endif | 1433 | #endif |
1429 | }; | 1434 | }; |
1430 | 1435 | ||
diff --git a/net/can/bcm.c b/net/can/bcm.c index 95d7f32643ae..72720c710351 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -75,6 +75,7 @@ static __initdata const char banner[] = KERN_INFO | |||
75 | MODULE_DESCRIPTION("PF_CAN broadcast manager protocol"); | 75 | MODULE_DESCRIPTION("PF_CAN broadcast manager protocol"); |
76 | MODULE_LICENSE("Dual BSD/GPL"); | 76 | MODULE_LICENSE("Dual BSD/GPL"); |
77 | MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>"); | 77 | MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>"); |
78 | MODULE_ALIAS("can-proto-2"); | ||
78 | 79 | ||
79 | /* easy access to can_frame payload */ | 80 | /* easy access to can_frame payload */ |
80 | static inline u64 GET_U64(const struct can_frame *cp) | 81 | static inline u64 GET_U64(const struct can_frame *cp) |
@@ -1469,6 +1470,9 @@ static int bcm_release(struct socket *sock) | |||
1469 | bo->ifindex = 0; | 1470 | bo->ifindex = 0; |
1470 | } | 1471 | } |
1471 | 1472 | ||
1473 | sock_orphan(sk); | ||
1474 | sock->sk = NULL; | ||
1475 | |||
1472 | release_sock(sk); | 1476 | release_sock(sk); |
1473 | sock_put(sk); | 1477 | sock_put(sk); |
1474 | 1478 | ||
diff --git a/net/can/raw.c b/net/can/raw.c index 6aa154e806ae..f4cc44548bda 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -62,6 +62,7 @@ static __initdata const char banner[] = | |||
62 | MODULE_DESCRIPTION("PF_CAN raw protocol"); | 62 | MODULE_DESCRIPTION("PF_CAN raw protocol"); |
63 | MODULE_LICENSE("Dual BSD/GPL"); | 63 | MODULE_LICENSE("Dual BSD/GPL"); |
64 | MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>"); | 64 | MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>"); |
65 | MODULE_ALIAS("can-proto-1"); | ||
65 | 66 | ||
66 | #define MASK_ALL 0 | 67 | #define MASK_ALL 0 |
67 | 68 | ||
@@ -306,6 +307,9 @@ static int raw_release(struct socket *sock) | |||
306 | ro->bound = 0; | 307 | ro->bound = 0; |
307 | ro->count = 0; | 308 | ro->count = 0; |
308 | 309 | ||
310 | sock_orphan(sk); | ||
311 | sock->sk = NULL; | ||
312 | |||
309 | release_sock(sk); | 313 | release_sock(sk); |
310 | sock_put(sk); | 314 | sock_put(sk); |
311 | 315 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index ba5d2116aea1..bbb25be7ddfe 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -631,7 +631,7 @@ set_rcvbuf: | |||
631 | 631 | ||
632 | case SO_TIMESTAMPING: | 632 | case SO_TIMESTAMPING: |
633 | if (val & ~SOF_TIMESTAMPING_MASK) { | 633 | if (val & ~SOF_TIMESTAMPING_MASK) { |
634 | ret = EINVAL; | 634 | ret = -EINVAL; |
635 | break; | 635 | break; |
636 | } | 636 | } |
637 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, | 637 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, |
@@ -919,13 +919,19 @@ static inline void sock_lock_init(struct sock *sk) | |||
919 | af_family_keys + sk->sk_family); | 919 | af_family_keys + sk->sk_family); |
920 | } | 920 | } |
921 | 921 | ||
922 | /* | ||
923 | * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet, | ||
924 | * even temporarly, because of RCU lookups. sk_node should also be left as is. | ||
925 | */ | ||
922 | static void sock_copy(struct sock *nsk, const struct sock *osk) | 926 | static void sock_copy(struct sock *nsk, const struct sock *osk) |
923 | { | 927 | { |
924 | #ifdef CONFIG_SECURITY_NETWORK | 928 | #ifdef CONFIG_SECURITY_NETWORK |
925 | void *sptr = nsk->sk_security; | 929 | void *sptr = nsk->sk_security; |
926 | #endif | 930 | #endif |
927 | 931 | BUILD_BUG_ON(offsetof(struct sock, sk_copy_start) != | |
928 | memcpy(nsk, osk, osk->sk_prot->obj_size); | 932 | sizeof(osk->sk_node) + sizeof(osk->sk_refcnt)); |
933 | memcpy(&nsk->sk_copy_start, &osk->sk_copy_start, | ||
934 | osk->sk_prot->obj_size - offsetof(struct sock, sk_copy_start)); | ||
929 | #ifdef CONFIG_SECURITY_NETWORK | 935 | #ifdef CONFIG_SECURITY_NETWORK |
930 | nsk->sk_security = sptr; | 936 | nsk->sk_security = sptr; |
931 | security_sk_clone(osk, nsk); | 937 | security_sk_clone(osk, nsk); |
@@ -1140,6 +1146,11 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
1140 | 1146 | ||
1141 | newsk->sk_err = 0; | 1147 | newsk->sk_err = 0; |
1142 | newsk->sk_priority = 0; | 1148 | newsk->sk_priority = 0; |
1149 | /* | ||
1150 | * Before updating sk_refcnt, we must commit prior changes to memory | ||
1151 | * (Documentation/RCU/rculist_nulls.txt for details) | ||
1152 | */ | ||
1153 | smp_wmb(); | ||
1143 | atomic_set(&newsk->sk_refcnt, 2); | 1154 | atomic_set(&newsk->sk_refcnt, 2); |
1144 | 1155 | ||
1145 | /* | 1156 | /* |
@@ -1855,6 +1866,11 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
1855 | 1866 | ||
1856 | sk->sk_stamp = ktime_set(-1L, 0); | 1867 | sk->sk_stamp = ktime_set(-1L, 0); |
1857 | 1868 | ||
1869 | /* | ||
1870 | * Before updating sk_refcnt, we must commit prior changes to memory | ||
1871 | * (Documentation/RCU/rculist_nulls.txt for details) | ||
1872 | */ | ||
1873 | smp_wmb(); | ||
1858 | atomic_set(&sk->sk_refcnt, 1); | 1874 | atomic_set(&sk->sk_refcnt, 1); |
1859 | atomic_set(&sk->sk_wmem_alloc, 1); | 1875 | atomic_set(&sk->sk_wmem_alloc, 1); |
1860 | atomic_set(&sk->sk_drops, 0); | 1876 | atomic_set(&sk->sk_drops, 0); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5a1ca2698c88..6d88219c5e22 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1160,6 +1160,7 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { | |||
1160 | #ifdef CONFIG_TCP_MD5SIG | 1160 | #ifdef CONFIG_TCP_MD5SIG |
1161 | static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { | 1161 | static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { |
1162 | .md5_lookup = tcp_v4_reqsk_md5_lookup, | 1162 | .md5_lookup = tcp_v4_reqsk_md5_lookup, |
1163 | .calc_md5_hash = tcp_v4_md5_hash_skb, | ||
1163 | }; | 1164 | }; |
1164 | #endif | 1165 | #endif |
1165 | 1166 | ||
@@ -1373,7 +1374,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1373 | */ | 1374 | */ |
1374 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); | 1375 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); |
1375 | if (newkey != NULL) | 1376 | if (newkey != NULL) |
1376 | tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr, | 1377 | tcp_v4_md5_do_add(newsk, newinet->daddr, |
1377 | newkey, key->keylen); | 1378 | newkey, key->keylen); |
1378 | newsk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 1379 | newsk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
1379 | } | 1380 | } |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 5bdf08d312d9..bd62712848fa 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -2261,7 +2261,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2261 | #ifdef CONFIG_TCP_MD5SIG | 2261 | #ifdef CONFIG_TCP_MD5SIG |
2262 | /* Okay, we have all we need - do the md5 hash if needed */ | 2262 | /* Okay, we have all we need - do the md5 hash if needed */ |
2263 | if (md5) { | 2263 | if (md5) { |
2264 | tp->af_specific->calc_md5_hash(md5_hash_location, | 2264 | tcp_rsk(req)->af_specific->calc_md5_hash(md5_hash_location, |
2265 | md5, NULL, req, skb); | 2265 | md5, NULL, req, skb); |
2266 | } | 2266 | } |
2267 | #endif | 2267 | #endif |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 58810c65b635..d849dd53b788 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -896,6 +896,7 @@ struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | |||
896 | #ifdef CONFIG_TCP_MD5SIG | 896 | #ifdef CONFIG_TCP_MD5SIG |
897 | static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | 897 | static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { |
898 | .md5_lookup = tcp_v6_reqsk_md5_lookup, | 898 | .md5_lookup = tcp_v6_reqsk_md5_lookup, |
899 | .calc_md5_hash = tcp_v6_md5_hash_skb, | ||
899 | }; | 900 | }; |
900 | #endif | 901 | #endif |
901 | 902 | ||
@@ -1441,7 +1442,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1441 | */ | 1442 | */ |
1442 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); | 1443 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); |
1443 | if (newkey != NULL) | 1444 | if (newkey != NULL) |
1444 | tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr, | 1445 | tcp_v6_md5_do_add(newsk, &newnp->daddr, |
1445 | newkey, key->keylen); | 1446 | newkey, key->keylen); |
1446 | } | 1447 | } |
1447 | #endif | 1448 | #endif |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 7508f11c5b39..b5869b9574b0 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -561,23 +561,38 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, | |||
561 | } | 561 | } |
562 | } | 562 | } |
563 | 563 | ||
564 | ct = kmem_cache_zalloc(nf_conntrack_cachep, gfp); | 564 | /* |
565 | * Do not use kmem_cache_zalloc(), as this cache uses | ||
566 | * SLAB_DESTROY_BY_RCU. | ||
567 | */ | ||
568 | ct = kmem_cache_alloc(nf_conntrack_cachep, gfp); | ||
565 | if (ct == NULL) { | 569 | if (ct == NULL) { |
566 | pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n"); | 570 | pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n"); |
567 | atomic_dec(&net->ct.count); | 571 | atomic_dec(&net->ct.count); |
568 | return ERR_PTR(-ENOMEM); | 572 | return ERR_PTR(-ENOMEM); |
569 | } | 573 | } |
570 | 574 | /* | |
575 | * Let ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.next | ||
576 | * and ct->tuplehash[IP_CT_DIR_REPLY].hnnode.next unchanged. | ||
577 | */ | ||
578 | memset(&ct->tuplehash[IP_CT_DIR_MAX], 0, | ||
579 | sizeof(*ct) - offsetof(struct nf_conn, tuplehash[IP_CT_DIR_MAX])); | ||
571 | spin_lock_init(&ct->lock); | 580 | spin_lock_init(&ct->lock); |
572 | atomic_set(&ct->ct_general.use, 1); | ||
573 | ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; | 581 | ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; |
582 | ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL; | ||
574 | ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; | 583 | ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; |
584 | ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev = NULL; | ||
575 | /* Don't set timer yet: wait for confirmation */ | 585 | /* Don't set timer yet: wait for confirmation */ |
576 | setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct); | 586 | setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct); |
577 | #ifdef CONFIG_NET_NS | 587 | #ifdef CONFIG_NET_NS |
578 | ct->ct_net = net; | 588 | ct->ct_net = net; |
579 | #endif | 589 | #endif |
580 | 590 | ||
591 | /* | ||
592 | * changes to lookup keys must be done before setting refcnt to 1 | ||
593 | */ | ||
594 | smp_wmb(); | ||
595 | atomic_set(&ct->ct_general.use, 1); | ||
581 | return ct; | 596 | return ct; |
582 | } | 597 | } |
583 | EXPORT_SYMBOL_GPL(nf_conntrack_alloc); | 598 | EXPORT_SYMBOL_GPL(nf_conntrack_alloc); |
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index 863e40977a4d..0f482e2440b4 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c | |||
@@ -330,7 +330,8 @@ static bool xt_osf_match_packet(const struct sk_buff *skb, | |||
330 | fcount++; | 330 | fcount++; |
331 | 331 | ||
332 | if (info->flags & XT_OSF_LOG) | 332 | if (info->flags & XT_OSF_LOG) |
333 | nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL, | 333 | nf_log_packet(p->family, p->hooknum, skb, |
334 | p->in, p->out, NULL, | ||
334 | "%s [%s:%s] : %pi4:%d -> %pi4:%d hops=%d\n", | 335 | "%s [%s:%s] : %pi4:%d -> %pi4:%d hops=%d\n", |
335 | f->genre, f->version, f->subtype, | 336 | f->genre, f->version, f->subtype, |
336 | &ip->saddr, ntohs(tcp->source), | 337 | &ip->saddr, ntohs(tcp->source), |
@@ -345,7 +346,7 @@ static bool xt_osf_match_packet(const struct sk_buff *skb, | |||
345 | rcu_read_unlock(); | 346 | rcu_read_unlock(); |
346 | 347 | ||
347 | if (!fcount && (info->flags & XT_OSF_LOG)) | 348 | if (!fcount && (info->flags & XT_OSF_LOG)) |
348 | nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL, | 349 | nf_log_packet(p->family, p->hooknum, skb, p->in, p->out, NULL, |
349 | "Remote OS is not known: %pi4:%u -> %pi4:%u\n", | 350 | "Remote OS is not known: %pi4:%u -> %pi4:%u\n", |
350 | &ip->saddr, ntohs(tcp->source), | 351 | &ip->saddr, ntohs(tcp->source), |
351 | &ip->daddr, ntohs(tcp->dest)); | 352 | &ip->daddr, ntohs(tcp->dest)); |