aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiuseppe CAVALLARO <peppe.cavallaro@st.com>2010-04-13 16:21:12 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-14 07:49:50 -0400
commit56b106ae7b1f6b7cef4ef7e79a03b59cfc940923 (patch)
tree3bf4908dd7a31231480f7f7289e6660b49bd41e3
parent3c32be635c18ead00d460b7bdad1da52622ff40f (diff)
stmmac: rework normal and enhanced descriptors
Currently the driver assumes that the mac10/100 can only use the normal descriptor structure and the gmac can only use the enhanced structures. This patch removes the descriptor's code from the dma files and adds two new files just for handling the normal and enhanced descriptors. Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/stmmac/Makefile2
-rw-r--r--drivers/net/stmmac/common.h15
-rw-r--r--drivers/net/stmmac/dwmac100.h12
-rw-r--r--drivers/net/stmmac/dwmac1000.h11
-rw-r--r--drivers/net/stmmac/dwmac1000_core.c27
-rw-r--r--drivers/net/stmmac/dwmac1000_dma.c327
-rw-r--r--drivers/net/stmmac/dwmac100_core.c3
-rw-r--r--drivers/net/stmmac/dwmac100_dma.c223
-rw-r--r--drivers/net/stmmac/enh_desc.c342
-rw-r--r--drivers/net/stmmac/norm_desc.c240
-rw-r--r--drivers/net/stmmac/stmmac.h2
-rw-r--r--drivers/net/stmmac/stmmac_main.c7
12 files changed, 627 insertions, 584 deletions
diff --git a/drivers/net/stmmac/Makefile b/drivers/net/stmmac/Makefile
index b14bd563b1e2..9691733ddb8e 100644
--- a/drivers/net/stmmac/Makefile
+++ b/drivers/net/stmmac/Makefile
@@ -2,4 +2,4 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o
2stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o 2stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o
3stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o \ 3stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o \
4 dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ 4 dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
5 dwmac100_core.o dwmac100_dma.o $(stmmac-y) 5 dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o $(stmmac-y)
diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h
index 2a58172e986a..bd3b78510706 100644
--- a/drivers/net/stmmac/common.h
+++ b/drivers/net/stmmac/common.h
@@ -22,8 +22,21 @@
22 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 22 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
23*******************************************************************************/ 23*******************************************************************************/
24 24
25#include "descs.h"
26#include <linux/netdevice.h> 25#include <linux/netdevice.h>
26#include "descs.h"
27
28#undef CHIP_DEBUG_PRINT
29/* Turn-on extra printk debug for MAC core, dma and descriptors */
30/* #define CHIP_DEBUG_PRINT */
31
32#ifdef CHIP_DEBUG_PRINT
33#define CHIP_DBG(fmt, args...) printk(fmt, ## args)
34#else
35#define CHIP_DBG(fmt, args...) do { } while (0)
36#endif
37
38#undef FRAME_FILTER_DEBUG
39/* #define FRAME_FILTER_DEBUG */
27 40
28struct stmmac_extra_stats { 41struct stmmac_extra_stats {
29 /* Transmit errors */ 42 /* Transmit errors */
diff --git a/drivers/net/stmmac/dwmac100.h b/drivers/net/stmmac/dwmac100.h
index 9f4ba2e76575..97956cbf1cb4 100644
--- a/drivers/net/stmmac/dwmac100.h
+++ b/drivers/net/stmmac/dwmac100.h
@@ -118,16 +118,4 @@ enum ttc_control {
118#define DMA_MISSED_FRAME_OVE_M 0x00010000 /* Missed Frame Overflow */ 118#define DMA_MISSED_FRAME_OVE_M 0x00010000 /* Missed Frame Overflow */
119#define DMA_MISSED_FRAME_M_CNTR 0x0000ffff /* Missed Frame Couinter */ 119#define DMA_MISSED_FRAME_M_CNTR 0x0000ffff /* Missed Frame Couinter */
120 120
121#undef DWMAC100_DEBUG
122/* #define DWMAC100__DEBUG */
123#undef FRAME_FILTER_DEBUG
124/* #define FRAME_FILTER_DEBUG */
125#ifdef DWMAC100__DEBUG
126#define DBG(fmt, args...) printk(fmt, ## args)
127#else
128#define DBG(fmt, args...) do { } while (0)
129#endif
130
131extern struct stmmac_dma_ops dwmac100_dma_ops; 121extern struct stmmac_dma_ops dwmac100_dma_ops;
132extern struct stmmac_desc_ops dwmac100_desc_ops;
133
diff --git a/drivers/net/stmmac/dwmac1000.h b/drivers/net/stmmac/dwmac1000.h
index 62dca0e384e7..3b784fc9320b 100644
--- a/drivers/net/stmmac/dwmac1000.h
+++ b/drivers/net/stmmac/dwmac1000.h
@@ -206,15 +206,4 @@ enum rtc_control {
206#define GMAC_MMC_TX_INTR 0x108 206#define GMAC_MMC_TX_INTR 0x108
207#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 207#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
208 208
209#undef DWMAC1000_DEBUG
210/* #define DWMAC1000__DEBUG */
211#undef FRAME_FILTER_DEBUG
212/* #define FRAME_FILTER_DEBUG */
213#ifdef DWMAC1000__DEBUG
214#define DBG(fmt, args...) printk(fmt, ## args)
215#else
216#define DBG(fmt, args...) do { } while (0)
217#endif
218
219extern struct stmmac_dma_ops dwmac1000_dma_ops; 209extern struct stmmac_dma_ops dwmac1000_dma_ops;
220extern struct stmmac_desc_ops dwmac1000_desc_ops;
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c
index f9c7c1cbda93..0aa89ae9b8e9 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/stmmac/dwmac1000_core.c
@@ -83,8 +83,8 @@ static void dwmac1000_set_filter(struct net_device *dev)
83 unsigned long ioaddr = dev->base_addr; 83 unsigned long ioaddr = dev->base_addr;
84 unsigned int value = 0; 84 unsigned int value = 0;
85 85
86 DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n", 86 CHIP_DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n",
87 __func__, netdev_mc_count(dev), netdev_uc_count(dev)); 87 __func__, netdev_mc_count(dev), netdev_uc_count(dev));
88 88
89 if (dev->flags & IFF_PROMISC) 89 if (dev->flags & IFF_PROMISC)
90 value = GMAC_FRAME_FILTER_PR; 90 value = GMAC_FRAME_FILTER_PR;
@@ -136,7 +136,7 @@ static void dwmac1000_set_filter(struct net_device *dev)
136#endif 136#endif
137 writel(value, ioaddr + GMAC_FRAME_FILTER); 137 writel(value, ioaddr + GMAC_FRAME_FILTER);
138 138
139 DBG(KERN_INFO "\tFrame Filter reg: 0x%08x\n\tHash regs: " 139 CHIP_DBG(KERN_INFO "\tFrame Filter reg: 0x%08x\n\tHash regs: "
140 "HI 0x%08x, LO 0x%08x\n", readl(ioaddr + GMAC_FRAME_FILTER), 140 "HI 0x%08x, LO 0x%08x\n", readl(ioaddr + GMAC_FRAME_FILTER),
141 readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW)); 141 readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW));
142 142
@@ -148,18 +148,18 @@ static void dwmac1000_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
148{ 148{
149 unsigned int flow = 0; 149 unsigned int flow = 0;
150 150
151 DBG(KERN_DEBUG "GMAC Flow-Control:\n"); 151 CHIP_DBG(KERN_DEBUG "GMAC Flow-Control:\n");
152 if (fc & FLOW_RX) { 152 if (fc & FLOW_RX) {
153 DBG(KERN_DEBUG "\tReceive Flow-Control ON\n"); 153 CHIP_DBG(KERN_DEBUG "\tReceive Flow-Control ON\n");
154 flow |= GMAC_FLOW_CTRL_RFE; 154 flow |= GMAC_FLOW_CTRL_RFE;
155 } 155 }
156 if (fc & FLOW_TX) { 156 if (fc & FLOW_TX) {
157 DBG(KERN_DEBUG "\tTransmit Flow-Control ON\n"); 157 CHIP_DBG(KERN_DEBUG "\tTransmit Flow-Control ON\n");
158 flow |= GMAC_FLOW_CTRL_TFE; 158 flow |= GMAC_FLOW_CTRL_TFE;
159 } 159 }
160 160
161 if (duplex) { 161 if (duplex) {
162 DBG(KERN_DEBUG "\tduplex mode: pause time: %d\n", pause_time); 162 CHIP_DBG(KERN_DEBUG "\tduplex mode: PAUSE %d\n", pause_time);
163 flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT); 163 flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT);
164 } 164 }
165 165
@@ -172,10 +172,10 @@ static void dwmac1000_pmt(unsigned long ioaddr, unsigned long mode)
172 unsigned int pmt = 0; 172 unsigned int pmt = 0;
173 173
174 if (mode == WAKE_MAGIC) { 174 if (mode == WAKE_MAGIC) {
175 DBG(KERN_DEBUG "GMAC: WOL Magic frame\n"); 175 CHIP_DBG(KERN_DEBUG "GMAC: WOL Magic frame\n");
176 pmt |= power_down | magic_pkt_en; 176 pmt |= power_down | magic_pkt_en;
177 } else if (mode == WAKE_UCAST) { 177 } else if (mode == WAKE_UCAST) {
178 DBG(KERN_DEBUG "GMAC: WOL on global unicast\n"); 178 CHIP_DBG(KERN_DEBUG "GMAC: WOL on global unicast\n");
179 pmt |= global_unicast; 179 pmt |= global_unicast;
180 } 180 }
181 181
@@ -190,16 +190,16 @@ static void dwmac1000_irq_status(unsigned long ioaddr)
190 190
191 /* Not used events (e.g. MMC interrupts) are not handled. */ 191 /* Not used events (e.g. MMC interrupts) are not handled. */
192 if ((intr_status & mmc_tx_irq)) 192 if ((intr_status & mmc_tx_irq))
193 DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n", 193 CHIP_DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n",
194 readl(ioaddr + GMAC_MMC_TX_INTR)); 194 readl(ioaddr + GMAC_MMC_TX_INTR));
195 if (unlikely(intr_status & mmc_rx_irq)) 195 if (unlikely(intr_status & mmc_rx_irq))
196 DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n", 196 CHIP_DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n",
197 readl(ioaddr + GMAC_MMC_RX_INTR)); 197 readl(ioaddr + GMAC_MMC_RX_INTR));
198 if (unlikely(intr_status & mmc_rx_csum_offload_irq)) 198 if (unlikely(intr_status & mmc_rx_csum_offload_irq))
199 DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n", 199 CHIP_DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n",
200 readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD)); 200 readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
201 if (unlikely(intr_status & pmt_irq)) { 201 if (unlikely(intr_status & pmt_irq)) {
202 DBG(KERN_DEBUG "GMAC: received Magic frame\n"); 202 CHIP_DBG(KERN_DEBUG "GMAC: received Magic frame\n");
203 /* clear the PMT bits 5 and 6 by reading the PMT 203 /* clear the PMT bits 5 and 6 by reading the PMT
204 * status register. */ 204 * status register. */
205 readl(ioaddr + GMAC_PMT); 205 readl(ioaddr + GMAC_PMT);
@@ -230,7 +230,6 @@ struct mac_device_info *dwmac1000_setup(unsigned long ioaddr)
230 mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL); 230 mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
231 231
232 mac->mac = &dwmac1000_ops; 232 mac->mac = &dwmac1000_ops;
233 mac->desc = &dwmac1000_desc_ops;
234 mac->dma = &dwmac1000_dma_ops; 233 mac->dma = &dwmac1000_dma_ops;
235 234
236 mac->pmt = PMT_SUPPORTED; 235 mac->pmt = PMT_SUPPORTED;
diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/stmmac/dwmac1000_dma.c
index 39d436a2da68..8d3ea99d8adf 100644
--- a/drivers/net/stmmac/dwmac1000_dma.c
+++ b/drivers/net/stmmac/dwmac1000_dma.c
@@ -3,7 +3,7 @@
3 DWC Ether MAC 10/100/1000 Universal version 3.41a has been used for 3 DWC Ether MAC 10/100/1000 Universal version 3.41a has been used for
4 developing this code. 4 developing this code.
5 5
6 This contains the functions to handle the dma and descriptors. 6 This contains the functions to handle the dma.
7 7
8 Copyright (C) 2007-2009 STMicroelectronics Ltd 8 Copyright (C) 2007-2009 STMicroelectronics Ltd
9 9
@@ -73,14 +73,14 @@ static void dwmac1000_dma_operation_mode(unsigned long ioaddr, int txmode,
73 u32 csr6 = readl(ioaddr + DMA_CONTROL); 73 u32 csr6 = readl(ioaddr + DMA_CONTROL);
74 74
75 if (txmode == SF_DMA_MODE) { 75 if (txmode == SF_DMA_MODE) {
76 DBG(KERN_DEBUG "GMAC: enabling TX store and forward mode\n"); 76 CHIP_DBG(KERN_DEBUG "GMAC: enable TX store and forward mode\n");
77 /* Transmit COE type 2 cannot be done in cut-through mode. */ 77 /* Transmit COE type 2 cannot be done in cut-through mode. */
78 csr6 |= DMA_CONTROL_TSF; 78 csr6 |= DMA_CONTROL_TSF;
79 /* Operating on second frame increase the performance 79 /* Operating on second frame increase the performance
80 * especially when transmit store-and-forward is used.*/ 80 * especially when transmit store-and-forward is used.*/
81 csr6 |= DMA_CONTROL_OSF; 81 csr6 |= DMA_CONTROL_OSF;
82 } else { 82 } else {
83 DBG(KERN_DEBUG "GMAC: disabling TX store and forward mode" 83 CHIP_DBG(KERN_DEBUG "GMAC: disabling TX store and forward mode"
84 " (threshold = %d)\n", txmode); 84 " (threshold = %d)\n", txmode);
85 csr6 &= ~DMA_CONTROL_TSF; 85 csr6 &= ~DMA_CONTROL_TSF;
86 csr6 &= DMA_CONTROL_TC_TX_MASK; 86 csr6 &= DMA_CONTROL_TC_TX_MASK;
@@ -98,10 +98,10 @@ static void dwmac1000_dma_operation_mode(unsigned long ioaddr, int txmode,
98 } 98 }
99 99
100 if (rxmode == SF_DMA_MODE) { 100 if (rxmode == SF_DMA_MODE) {
101 DBG(KERN_DEBUG "GMAC: enabling RX store and forward mode\n"); 101 CHIP_DBG(KERN_DEBUG "GMAC: enable RX store and forward mode\n");
102 csr6 |= DMA_CONTROL_RSF; 102 csr6 |= DMA_CONTROL_RSF;
103 } else { 103 } else {
104 DBG(KERN_DEBUG "GMAC: disabling RX store and forward mode" 104 CHIP_DBG(KERN_DEBUG "GMAC: disabling RX store and forward mode"
105 " (threshold = %d)\n", rxmode); 105 " (threshold = %d)\n", rxmode);
106 csr6 &= ~DMA_CONTROL_RSF; 106 csr6 &= ~DMA_CONTROL_RSF;
107 csr6 &= DMA_CONTROL_TC_RX_MASK; 107 csr6 &= DMA_CONTROL_TC_RX_MASK;
@@ -141,305 +141,6 @@ static void dwmac1000_dump_dma_regs(unsigned long ioaddr)
141 return; 141 return;
142} 142}
143 143
144static int dwmac1000_get_tx_frame_status(void *data,
145 struct stmmac_extra_stats *x,
146 struct dma_desc *p, unsigned long ioaddr)
147{
148 int ret = 0;
149 struct net_device_stats *stats = (struct net_device_stats *)data;
150
151 if (unlikely(p->des01.etx.error_summary)) {
152 DBG(KERN_ERR "GMAC TX error... 0x%08x\n", p->des01.etx);
153 if (unlikely(p->des01.etx.jabber_timeout)) {
154 DBG(KERN_ERR "\tjabber_timeout error\n");
155 x->tx_jabber++;
156 }
157
158 if (unlikely(p->des01.etx.frame_flushed)) {
159 DBG(KERN_ERR "\tframe_flushed error\n");
160 x->tx_frame_flushed++;
161 dwmac1000_flush_tx_fifo(ioaddr);
162 }
163
164 if (unlikely(p->des01.etx.loss_carrier)) {
165 DBG(KERN_ERR "\tloss_carrier error\n");
166 x->tx_losscarrier++;
167 stats->tx_carrier_errors++;
168 }
169 if (unlikely(p->des01.etx.no_carrier)) {
170 DBG(KERN_ERR "\tno_carrier error\n");
171 x->tx_carrier++;
172 stats->tx_carrier_errors++;
173 }
174 if (unlikely(p->des01.etx.late_collision)) {
175 DBG(KERN_ERR "\tlate_collision error\n");
176 stats->collisions += p->des01.etx.collision_count;
177 }
178 if (unlikely(p->des01.etx.excessive_collisions)) {
179 DBG(KERN_ERR "\texcessive_collisions\n");
180 stats->collisions += p->des01.etx.collision_count;
181 }
182 if (unlikely(p->des01.etx.excessive_deferral)) {
183 DBG(KERN_INFO "\texcessive tx_deferral\n");
184 x->tx_deferred++;
185 }
186
187 if (unlikely(p->des01.etx.underflow_error)) {
188 DBG(KERN_ERR "\tunderflow error\n");
189 dwmac1000_flush_tx_fifo(ioaddr);
190 x->tx_underflow++;
191 }
192
193 if (unlikely(p->des01.etx.ip_header_error)) {
194 DBG(KERN_ERR "\tTX IP header csum error\n");
195 x->tx_ip_header_error++;
196 }
197
198 if (unlikely(p->des01.etx.payload_error)) {
199 DBG(KERN_ERR "\tAddr/Payload csum error\n");
200 x->tx_payload_error++;
201 dwmac1000_flush_tx_fifo(ioaddr);
202 }
203
204 ret = -1;
205 }
206
207 if (unlikely(p->des01.etx.deferred)) {
208 DBG(KERN_INFO "GMAC TX status: tx deferred\n");
209 x->tx_deferred++;
210 }
211#ifdef STMMAC_VLAN_TAG_USED
212 if (p->des01.etx.vlan_frame) {
213 DBG(KERN_INFO "GMAC TX status: VLAN frame\n");
214 x->tx_vlan++;
215 }
216#endif
217
218 return ret;
219}
220
221static int dwmac1000_get_tx_len(struct dma_desc *p)
222{
223 return p->des01.etx.buffer1_size;
224}
225
226static int dwmac1000_coe_rdes0(int ipc_err, int type, int payload_err)
227{
228 int ret = good_frame;
229 u32 status = (type << 2 | ipc_err << 1 | payload_err) & 0x7;
230
231 /* bits 5 7 0 | Frame status
232 * ----------------------------------------------------------
233 * 0 0 0 | IEEE 802.3 Type frame (length < 1536 octects)
234 * 1 0 0 | IPv4/6 No CSUM errorS.
235 * 1 0 1 | IPv4/6 CSUM PAYLOAD error
236 * 1 1 0 | IPv4/6 CSUM IP HR error
237 * 1 1 1 | IPv4/6 IP PAYLOAD AND HEADER errorS
238 * 0 0 1 | IPv4/6 unsupported IP PAYLOAD
239 * 0 1 1 | COE bypassed.. no IPv4/6 frame
240 * 0 1 0 | Reserved.
241 */
242 if (status == 0x0) {
243 DBG(KERN_INFO "RX Des0 status: IEEE 802.3 Type frame.\n");
244 ret = good_frame;
245 } else if (status == 0x4) {
246 DBG(KERN_INFO "RX Des0 status: IPv4/6 No CSUM errorS.\n");
247 ret = good_frame;
248 } else if (status == 0x5) {
249 DBG(KERN_ERR "RX Des0 status: IPv4/6 Payload Error.\n");
250 ret = csum_none;
251 } else if (status == 0x6) {
252 DBG(KERN_ERR "RX Des0 status: IPv4/6 Header Error.\n");
253 ret = csum_none;
254 } else if (status == 0x7) {
255 DBG(KERN_ERR
256 "RX Des0 status: IPv4/6 Header and Payload Error.\n");
257 ret = csum_none;
258 } else if (status == 0x1) {
259 DBG(KERN_ERR
260 "RX Des0 status: IPv4/6 unsupported IP PAYLOAD.\n");
261 ret = discard_frame;
262 } else if (status == 0x3) {
263 DBG(KERN_ERR "RX Des0 status: No IPv4, IPv6 frame.\n");
264 ret = discard_frame;
265 }
266 return ret;
267}
268
269static int dwmac1000_get_rx_frame_status(void *data,
270 struct stmmac_extra_stats *x, struct dma_desc *p)
271{
272 int ret = good_frame;
273 struct net_device_stats *stats = (struct net_device_stats *)data;
274
275 if (unlikely(p->des01.erx.error_summary)) {
276 DBG(KERN_ERR "GMAC RX Error Summary... 0x%08x\n", p->des01.erx);
277 if (unlikely(p->des01.erx.descriptor_error)) {
278 DBG(KERN_ERR "\tdescriptor error\n");
279 x->rx_desc++;
280 stats->rx_length_errors++;
281 }
282 if (unlikely(p->des01.erx.overflow_error)) {
283 DBG(KERN_ERR "\toverflow error\n");
284 x->rx_gmac_overflow++;
285 }
286
287 if (unlikely(p->des01.erx.ipc_csum_error))
288 DBG(KERN_ERR "\tIPC Csum Error/Giant frame\n");
289
290 if (unlikely(p->des01.erx.late_collision)) {
291 DBG(KERN_ERR "\tlate_collision error\n");
292 stats->collisions++;
293 stats->collisions++;
294 }
295 if (unlikely(p->des01.erx.receive_watchdog)) {
296 DBG(KERN_ERR "\treceive_watchdog error\n");
297 x->rx_watchdog++;
298 }
299 if (unlikely(p->des01.erx.error_gmii)) {
300 DBG(KERN_ERR "\tReceive Error\n");
301 x->rx_mii++;
302 }
303 if (unlikely(p->des01.erx.crc_error)) {
304 DBG(KERN_ERR "\tCRC error\n");
305 x->rx_crc++;
306 stats->rx_crc_errors++;
307 }
308 ret = discard_frame;
309 }
310
311 /* After a payload csum error, the ES bit is set.
312 * It doesn't match with the information reported into the databook.
313 * At any rate, we need to understand if the CSUM hw computation is ok
314 * and report this info to the upper layers. */
315 ret = dwmac1000_coe_rdes0(p->des01.erx.ipc_csum_error,
316 p->des01.erx.frame_type, p->des01.erx.payload_csum_error);
317
318 if (unlikely(p->des01.erx.dribbling)) {
319 DBG(KERN_ERR "GMAC RX: dribbling error\n");
320 ret = discard_frame;
321 }
322 if (unlikely(p->des01.erx.sa_filter_fail)) {
323 DBG(KERN_ERR "GMAC RX : Source Address filter fail\n");
324 x->sa_rx_filter_fail++;
325 ret = discard_frame;
326 }
327 if (unlikely(p->des01.erx.da_filter_fail)) {
328 DBG(KERN_ERR "GMAC RX : Destination Address filter fail\n");
329 x->da_rx_filter_fail++;
330 ret = discard_frame;
331 }
332 if (unlikely(p->des01.erx.length_error)) {
333 DBG(KERN_ERR "GMAC RX: length_error error\n");
334 x->rx_length++;
335 ret = discard_frame;
336 }
337#ifdef STMMAC_VLAN_TAG_USED
338 if (p->des01.erx.vlan_tag) {
339 DBG(KERN_INFO "GMAC RX: VLAN frame tagged\n");
340 x->rx_vlan++;
341 }
342#endif
343 return ret;
344}
345
346static void dwmac1000_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
347 int disable_rx_ic)
348{
349 int i;
350 for (i = 0; i < ring_size; i++) {
351 p->des01.erx.own = 1;
352 p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
353 /* To support jumbo frames */
354 p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1;
355 if (i == ring_size - 1)
356 p->des01.erx.end_ring = 1;
357 if (disable_rx_ic)
358 p->des01.erx.disable_ic = 1;
359 p++;
360 }
361 return;
362}
363
364static void dwmac1000_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
365{
366 int i;
367
368 for (i = 0; i < ring_size; i++) {
369 p->des01.etx.own = 0;
370 if (i == ring_size - 1)
371 p->des01.etx.end_ring = 1;
372 p++;
373 }
374
375 return;
376}
377
378static int dwmac1000_get_tx_owner(struct dma_desc *p)
379{
380 return p->des01.etx.own;
381}
382
383static int dwmac1000_get_rx_owner(struct dma_desc *p)
384{
385 return p->des01.erx.own;
386}
387
388static void dwmac1000_set_tx_owner(struct dma_desc *p)
389{
390 p->des01.etx.own = 1;
391}
392
393static void dwmac1000_set_rx_owner(struct dma_desc *p)
394{
395 p->des01.erx.own = 1;
396}
397
398static int dwmac1000_get_tx_ls(struct dma_desc *p)
399{
400 return p->des01.etx.last_segment;
401}
402
403static void dwmac1000_release_tx_desc(struct dma_desc *p)
404{
405 int ter = p->des01.etx.end_ring;
406
407 memset(p, 0, sizeof(struct dma_desc));
408 p->des01.etx.end_ring = ter;
409
410 return;
411}
412
413static void dwmac1000_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
414 int csum_flag)
415{
416 p->des01.etx.first_segment = is_fs;
417 if (unlikely(len > BUF_SIZE_4KiB)) {
418 p->des01.etx.buffer1_size = BUF_SIZE_4KiB;
419 p->des01.etx.buffer2_size = len - BUF_SIZE_4KiB;
420 } else {
421 p->des01.etx.buffer1_size = len;
422 }
423 if (likely(csum_flag))
424 p->des01.etx.checksum_insertion = cic_full;
425}
426
427static void dwmac1000_clear_tx_ic(struct dma_desc *p)
428{
429 p->des01.etx.interrupt = 0;
430}
431
432static void dwmac1000_close_tx_desc(struct dma_desc *p)
433{
434 p->des01.etx.last_segment = 1;
435 p->des01.etx.interrupt = 1;
436}
437
438static int dwmac1000_get_rx_frame_len(struct dma_desc *p)
439{
440 return p->des01.erx.frame_length;
441}
442
443struct stmmac_dma_ops dwmac1000_dma_ops = { 144struct stmmac_dma_ops dwmac1000_dma_ops = {
444 .init = dwmac1000_dma_init, 145 .init = dwmac1000_dma_init,
445 .dump_regs = dwmac1000_dump_dma_regs, 146 .dump_regs = dwmac1000_dump_dma_regs,
@@ -454,21 +155,3 @@ struct stmmac_dma_ops dwmac1000_dma_ops = {
454 .stop_rx = dwmac_dma_stop_rx, 155 .stop_rx = dwmac_dma_stop_rx,
455 .dma_interrupt = dwmac_dma_interrupt, 156 .dma_interrupt = dwmac_dma_interrupt,
456}; 157};
457
458struct stmmac_desc_ops dwmac1000_desc_ops = {
459 .tx_status = dwmac1000_get_tx_frame_status,
460 .rx_status = dwmac1000_get_rx_frame_status,
461 .get_tx_len = dwmac1000_get_tx_len,
462 .init_rx_desc = dwmac1000_init_rx_desc,
463 .init_tx_desc = dwmac1000_init_tx_desc,
464 .get_tx_owner = dwmac1000_get_tx_owner,
465 .get_rx_owner = dwmac1000_get_rx_owner,
466 .release_tx_desc = dwmac1000_release_tx_desc,
467 .prepare_tx_desc = dwmac1000_prepare_tx_desc,
468 .clear_tx_ic = dwmac1000_clear_tx_ic,
469 .close_tx_desc = dwmac1000_close_tx_desc,
470 .get_tx_ls = dwmac1000_get_tx_ls,
471 .set_tx_owner = dwmac1000_set_tx_owner,
472 .set_rx_owner = dwmac1000_set_rx_owner,
473 .get_rx_frame_len = dwmac1000_get_rx_frame_len,
474};
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c
index 8ecb8c0b4d98..fab14a4cb14c 100644
--- a/drivers/net/stmmac/dwmac100_core.c
+++ b/drivers/net/stmmac/dwmac100_core.c
@@ -141,7 +141,7 @@ static void dwmac100_set_filter(struct net_device *dev)
141 141
142 writel(value, ioaddr + MAC_CONTROL); 142 writel(value, ioaddr + MAC_CONTROL);
143 143
144 DBG(KERN_INFO "%s: CTRL reg: 0x%08x Hash regs: " 144 CHIP_DBG(KERN_INFO "%s: CTRL reg: 0x%08x Hash regs: "
145 "HI 0x%08x, LO 0x%08x\n", 145 "HI 0x%08x, LO 0x%08x\n",
146 __func__, readl(ioaddr + MAC_CONTROL), 146 __func__, readl(ioaddr + MAC_CONTROL),
147 readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW)); 147 readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW));
@@ -188,7 +188,6 @@ struct mac_device_info *dwmac100_setup(unsigned long ioaddr)
188 pr_info("\tDWMAC100\n"); 188 pr_info("\tDWMAC100\n");
189 189
190 mac->mac = &dwmac100_ops; 190 mac->mac = &dwmac100_ops;
191 mac->desc = &dwmac100_desc_ops;
192 mac->dma = &dwmac100_dma_ops; 191 mac->dma = &dwmac100_dma_ops;
193 192
194 mac->pmt = PMT_NOT_SUPPORTED; 193 mac->pmt = PMT_NOT_SUPPORTED;
diff --git a/drivers/net/stmmac/dwmac100_dma.c b/drivers/net/stmmac/dwmac100_dma.c
index 7fcc52650505..96d098d68ad6 100644
--- a/drivers/net/stmmac/dwmac100_dma.c
+++ b/drivers/net/stmmac/dwmac100_dma.c
@@ -5,7 +5,7 @@
5 DWC Ether MAC 10/100 Universal version 4.0 has been used for developing 5 DWC Ether MAC 10/100 Universal version 4.0 has been used for developing
6 this code. 6 this code.
7 7
8 This contains the functions to handle the dma and descriptors. 8 This contains the functions to handle the dma.
9 9
10 Copyright (C) 2007-2009 STMicroelectronics Ltd 10 Copyright (C) 2007-2009 STMicroelectronics Ltd
11 11
@@ -79,14 +79,14 @@ static void dwmac100_dump_dma_regs(unsigned long ioaddr)
79{ 79{
80 int i; 80 int i;
81 81
82 DBG(KERN_DEBUG "DWMAC 100 DMA CSR\n"); 82 CHIP_DBG(KERN_DEBUG "DWMAC 100 DMA CSR\n");
83 for (i = 0; i < 9; i++) 83 for (i = 0; i < 9; i++)
84 pr_debug("\t CSR%d (offset 0x%x): 0x%08x\n", i, 84 pr_debug("\t CSR%d (offset 0x%x): 0x%08x\n", i,
85 (DMA_BUS_MODE + i * 4), 85 (DMA_BUS_MODE + i * 4),
86 readl(ioaddr + DMA_BUS_MODE + i * 4)); 86 readl(ioaddr + DMA_BUS_MODE + i * 4));
87 DBG(KERN_DEBUG "\t CSR20 (offset 0x%x): 0x%08x\n", 87 CHIP_DBG(KERN_DEBUG "\t CSR20 (offset 0x%x): 0x%08x\n",
88 DMA_CUR_TX_BUF_ADDR, readl(ioaddr + DMA_CUR_TX_BUF_ADDR)); 88 DMA_CUR_TX_BUF_ADDR, readl(ioaddr + DMA_CUR_TX_BUF_ADDR));
89 DBG(KERN_DEBUG "\t CSR21 (offset 0x%x): 0x%08x\n", 89 CHIP_DBG(KERN_DEBUG "\t CSR21 (offset 0x%x): 0x%08x\n",
90 DMA_CUR_RX_BUF_ADDR, readl(ioaddr + DMA_CUR_RX_BUF_ADDR)); 90 DMA_CUR_RX_BUF_ADDR, readl(ioaddr + DMA_CUR_RX_BUF_ADDR));
91 return; 91 return;
92} 92}
@@ -122,203 +122,6 @@ static void dwmac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x,
122 return; 122 return;
123} 123}
124 124
125static int dwmac100_get_tx_status(void *data, struct stmmac_extra_stats *x,
126 struct dma_desc *p, unsigned long ioaddr)
127{
128 int ret = 0;
129 struct net_device_stats *stats = (struct net_device_stats *)data;
130
131 if (unlikely(p->des01.tx.error_summary)) {
132 if (unlikely(p->des01.tx.underflow_error)) {
133 x->tx_underflow++;
134 stats->tx_fifo_errors++;
135 }
136 if (unlikely(p->des01.tx.no_carrier)) {
137 x->tx_carrier++;
138 stats->tx_carrier_errors++;
139 }
140 if (unlikely(p->des01.tx.loss_carrier)) {
141 x->tx_losscarrier++;
142 stats->tx_carrier_errors++;
143 }
144 if (unlikely((p->des01.tx.excessive_deferral) ||
145 (p->des01.tx.excessive_collisions) ||
146 (p->des01.tx.late_collision)))
147 stats->collisions += p->des01.tx.collision_count;
148 ret = -1;
149 }
150 if (unlikely(p->des01.tx.heartbeat_fail)) {
151 x->tx_heartbeat++;
152 stats->tx_heartbeat_errors++;
153 ret = -1;
154 }
155 if (unlikely(p->des01.tx.deferred))
156 x->tx_deferred++;
157
158 return ret;
159}
160
161static int dwmac100_get_tx_len(struct dma_desc *p)
162{
163 return p->des01.tx.buffer1_size;
164}
165
166/* This function verifies if each incoming frame has some errors
167 * and, if required, updates the multicast statistics.
168 * In case of success, it returns csum_none becasue the device
169 * is not able to compute the csum in HW. */
170static int dwmac100_get_rx_status(void *data, struct stmmac_extra_stats *x,
171 struct dma_desc *p)
172{
173 int ret = csum_none;
174 struct net_device_stats *stats = (struct net_device_stats *)data;
175
176 if (unlikely(p->des01.rx.last_descriptor == 0)) {
177 pr_warning("dwmac100 Error: Oversized Ethernet "
178 "frame spanned multiple buffers\n");
179 stats->rx_length_errors++;
180 return discard_frame;
181 }
182
183 if (unlikely(p->des01.rx.error_summary)) {
184 if (unlikely(p->des01.rx.descriptor_error))
185 x->rx_desc++;
186 if (unlikely(p->des01.rx.partial_frame_error))
187 x->rx_partial++;
188 if (unlikely(p->des01.rx.run_frame))
189 x->rx_runt++;
190 if (unlikely(p->des01.rx.frame_too_long))
191 x->rx_toolong++;
192 if (unlikely(p->des01.rx.collision)) {
193 x->rx_collision++;
194 stats->collisions++;
195 }
196 if (unlikely(p->des01.rx.crc_error)) {
197 x->rx_crc++;
198 stats->rx_crc_errors++;
199 }
200 ret = discard_frame;
201 }
202 if (unlikely(p->des01.rx.dribbling))
203 ret = discard_frame;
204
205 if (unlikely(p->des01.rx.length_error)) {
206 x->rx_length++;
207 ret = discard_frame;
208 }
209 if (unlikely(p->des01.rx.mii_error)) {
210 x->rx_mii++;
211 ret = discard_frame;
212 }
213 if (p->des01.rx.multicast_frame) {
214 x->rx_multicast++;
215 stats->multicast++;
216 }
217 return ret;
218}
219
220static void dwmac100_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
221 int disable_rx_ic)
222{
223 int i;
224 for (i = 0; i < ring_size; i++) {
225 p->des01.rx.own = 1;
226 p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
227 if (i == ring_size - 1)
228 p->des01.rx.end_ring = 1;
229 if (disable_rx_ic)
230 p->des01.rx.disable_ic = 1;
231 p++;
232 }
233 return;
234}
235
236static void dwmac100_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
237{
238 int i;
239 for (i = 0; i < ring_size; i++) {
240 p->des01.tx.own = 0;
241 if (i == ring_size - 1)
242 p->des01.tx.end_ring = 1;
243 p++;
244 }
245 return;
246}
247
248static int dwmac100_get_tx_owner(struct dma_desc *p)
249{
250 return p->des01.tx.own;
251}
252
253static int dwmac100_get_rx_owner(struct dma_desc *p)
254{
255 return p->des01.rx.own;
256}
257
258static void dwmac100_set_tx_owner(struct dma_desc *p)
259{
260 p->des01.tx.own = 1;
261}
262
263static void dwmac100_set_rx_owner(struct dma_desc *p)
264{
265 p->des01.rx.own = 1;
266}
267
268static int dwmac100_get_tx_ls(struct dma_desc *p)
269{
270 return p->des01.tx.last_segment;
271}
272
273static void dwmac100_release_tx_desc(struct dma_desc *p)
274{
275 int ter = p->des01.tx.end_ring;
276
277 /* clean field used within the xmit */
278 p->des01.tx.first_segment = 0;
279 p->des01.tx.last_segment = 0;
280 p->des01.tx.buffer1_size = 0;
281
282 /* clean status reported */
283 p->des01.tx.error_summary = 0;
284 p->des01.tx.underflow_error = 0;
285 p->des01.tx.no_carrier = 0;
286 p->des01.tx.loss_carrier = 0;
287 p->des01.tx.excessive_deferral = 0;
288 p->des01.tx.excessive_collisions = 0;
289 p->des01.tx.late_collision = 0;
290 p->des01.tx.heartbeat_fail = 0;
291 p->des01.tx.deferred = 0;
292
293 /* set termination field */
294 p->des01.tx.end_ring = ter;
295
296 return;
297}
298
299static void dwmac100_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
300 int csum_flag)
301{
302 p->des01.tx.first_segment = is_fs;
303 p->des01.tx.buffer1_size = len;
304}
305
306static void dwmac100_clear_tx_ic(struct dma_desc *p)
307{
308 p->des01.tx.interrupt = 0;
309}
310
311static void dwmac100_close_tx_desc(struct dma_desc *p)
312{
313 p->des01.tx.last_segment = 1;
314 p->des01.tx.interrupt = 1;
315}
316
317static int dwmac100_get_rx_frame_len(struct dma_desc *p)
318{
319 return p->des01.rx.frame_length;
320}
321
322struct stmmac_dma_ops dwmac100_dma_ops = { 125struct stmmac_dma_ops dwmac100_dma_ops = {
323 .init = dwmac100_dma_init, 126 .init = dwmac100_dma_init,
324 .dump_regs = dwmac100_dump_dma_regs, 127 .dump_regs = dwmac100_dump_dma_regs,
@@ -333,21 +136,3 @@ struct stmmac_dma_ops dwmac100_dma_ops = {
333 .stop_rx = dwmac_dma_stop_rx, 136 .stop_rx = dwmac_dma_stop_rx,
334 .dma_interrupt = dwmac_dma_interrupt, 137 .dma_interrupt = dwmac_dma_interrupt,
335}; 138};
336
337struct stmmac_desc_ops dwmac100_desc_ops = {
338 .tx_status = dwmac100_get_tx_status,
339 .rx_status = dwmac100_get_rx_status,
340 .get_tx_len = dwmac100_get_tx_len,
341 .init_rx_desc = dwmac100_init_rx_desc,
342 .init_tx_desc = dwmac100_init_tx_desc,
343 .get_tx_owner = dwmac100_get_tx_owner,
344 .get_rx_owner = dwmac100_get_rx_owner,
345 .release_tx_desc = dwmac100_release_tx_desc,
346 .prepare_tx_desc = dwmac100_prepare_tx_desc,
347 .clear_tx_ic = dwmac100_clear_tx_ic,
348 .close_tx_desc = dwmac100_close_tx_desc,
349 .get_tx_ls = dwmac100_get_tx_ls,
350 .set_tx_owner = dwmac100_set_tx_owner,
351 .set_rx_owner = dwmac100_set_rx_owner,
352 .get_rx_frame_len = dwmac100_get_rx_frame_len,
353};
diff --git a/drivers/net/stmmac/enh_desc.c b/drivers/net/stmmac/enh_desc.c
new file mode 100644
index 000000000000..e5ac2593dc68
--- /dev/null
+++ b/drivers/net/stmmac/enh_desc.c
@@ -0,0 +1,342 @@
1/*******************************************************************************
2 This contains the functions to handle the enhanced descriptors.
3
4 Copyright (C) 2007-2009 STMicroelectronics Ltd
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms and conditions of the GNU General Public License,
8 version 2, as published by the Free Software Foundation.
9
10 This program is distributed in the hope it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 more details.
14
15 You should have received a copy of the GNU General Public License along with
16 this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18
19 The full GNU General Public License is included in this distribution in
20 the file called "COPYING".
21
22 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
23*******************************************************************************/
24
25#include "common.h"
26
27static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
28 struct dma_desc *p, unsigned long ioaddr)
29{
30 int ret = 0;
31 struct net_device_stats *stats = (struct net_device_stats *)data;
32
33 if (unlikely(p->des01.etx.error_summary)) {
34 CHIP_DBG(KERN_ERR "GMAC TX error... 0x%08x\n", p->des01.etx);
35 if (unlikely(p->des01.etx.jabber_timeout)) {
36 CHIP_DBG(KERN_ERR "\tjabber_timeout error\n");
37 x->tx_jabber++;
38 }
39
40 if (unlikely(p->des01.etx.frame_flushed)) {
41 CHIP_DBG(KERN_ERR "\tframe_flushed error\n");
42 x->tx_frame_flushed++;
43 /*enh_desc_flush_tx_fifo(ioaddr);*/
44 }
45
46 if (unlikely(p->des01.etx.loss_carrier)) {
47 CHIP_DBG(KERN_ERR "\tloss_carrier error\n");
48 x->tx_losscarrier++;
49 stats->tx_carrier_errors++;
50 }
51 if (unlikely(p->des01.etx.no_carrier)) {
52 CHIP_DBG(KERN_ERR "\tno_carrier error\n");
53 x->tx_carrier++;
54 stats->tx_carrier_errors++;
55 }
56 if (unlikely(p->des01.etx.late_collision)) {
57 CHIP_DBG(KERN_ERR "\tlate_collision error\n");
58 stats->collisions += p->des01.etx.collision_count;
59 }
60 if (unlikely(p->des01.etx.excessive_collisions)) {
61 CHIP_DBG(KERN_ERR "\texcessive_collisions\n");
62 stats->collisions += p->des01.etx.collision_count;
63 }
64 if (unlikely(p->des01.etx.excessive_deferral)) {
65 CHIP_DBG(KERN_INFO "\texcessive tx_deferral\n");
66 x->tx_deferred++;
67 }
68
69 if (unlikely(p->des01.etx.underflow_error)) {
70 CHIP_DBG(KERN_ERR "\tunderflow error\n");
71 /*enh_desc_flush_tx_fifo(ioaddr);*/
72 x->tx_underflow++;
73 }
74
75 if (unlikely(p->des01.etx.ip_header_error)) {
76 CHIP_DBG(KERN_ERR "\tTX IP header csum error\n");
77 x->tx_ip_header_error++;
78 }
79
80 if (unlikely(p->des01.etx.payload_error)) {
81 CHIP_DBG(KERN_ERR "\tAddr/Payload csum error\n");
82 x->tx_payload_error++;
83 /*enh_desc_flush_tx_fifo(ioaddr);*/
84 }
85
86 ret = -1;
87 }
88
89 if (unlikely(p->des01.etx.deferred)) {
90 CHIP_DBG(KERN_INFO "GMAC TX status: tx deferred\n");
91 x->tx_deferred++;
92 }
93#ifdef STMMAC_VLAN_TAG_USED
94 if (p->des01.etx.vlan_frame) {
95 CHIP_DBG(KERN_INFO "GMAC TX status: VLAN frame\n");
96 x->tx_vlan++;
97 }
98#endif
99
100 return ret;
101}
102
103static int enh_desc_get_tx_len(struct dma_desc *p)
104{
105 return p->des01.etx.buffer1_size;
106}
107
108static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err)
109{
110 int ret = good_frame;
111 u32 status = (type << 2 | ipc_err << 1 | payload_err) & 0x7;
112
113 /* bits 5 7 0 | Frame status
114 * ----------------------------------------------------------
115 * 0 0 0 | IEEE 802.3 Type frame (length < 1536 octects)
116 * 1 0 0 | IPv4/6 No CSUM errorS.
117 * 1 0 1 | IPv4/6 CSUM PAYLOAD error
118 * 1 1 0 | IPv4/6 CSUM IP HR error
119 * 1 1 1 | IPv4/6 IP PAYLOAD AND HEADER errorS
120 * 0 0 1 | IPv4/6 unsupported IP PAYLOAD
121 * 0 1 1 | COE bypassed.. no IPv4/6 frame
122 * 0 1 0 | Reserved.
123 */
124 if (status == 0x0) {
125 CHIP_DBG(KERN_INFO "RX Des0 status: IEEE 802.3 Type frame.\n");
126 ret = good_frame;
127 } else if (status == 0x4) {
128 CHIP_DBG(KERN_INFO "RX Des0 status: IPv4/6 No CSUM errorS.\n");
129 ret = good_frame;
130 } else if (status == 0x5) {
131 CHIP_DBG(KERN_ERR "RX Des0 status: IPv4/6 Payload Error.\n");
132 ret = csum_none;
133 } else if (status == 0x6) {
134 CHIP_DBG(KERN_ERR "RX Des0 status: IPv4/6 Header Error.\n");
135 ret = csum_none;
136 } else if (status == 0x7) {
137 CHIP_DBG(KERN_ERR
138 "RX Des0 status: IPv4/6 Header and Payload Error.\n");
139 ret = csum_none;
140 } else if (status == 0x1) {
141 CHIP_DBG(KERN_ERR
142 "RX Des0 status: IPv4/6 unsupported IP PAYLOAD.\n");
143 ret = discard_frame;
144 } else if (status == 0x3) {
145 CHIP_DBG(KERN_ERR "RX Des0 status: No IPv4, IPv6 frame.\n");
146 ret = discard_frame;
147 }
148 return ret;
149}
150
151static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
152 struct dma_desc *p)
153{
154 int ret = good_frame;
155 struct net_device_stats *stats = (struct net_device_stats *)data;
156
157 if (unlikely(p->des01.erx.error_summary)) {
158 CHIP_DBG(KERN_ERR "GMAC RX Error Summary 0x%08x\n",
159 p->des01.erx);
160 if (unlikely(p->des01.erx.descriptor_error)) {
161 CHIP_DBG(KERN_ERR "\tdescriptor error\n");
162 x->rx_desc++;
163 stats->rx_length_errors++;
164 }
165 if (unlikely(p->des01.erx.overflow_error)) {
166 CHIP_DBG(KERN_ERR "\toverflow error\n");
167 x->rx_gmac_overflow++;
168 }
169
170 if (unlikely(p->des01.erx.ipc_csum_error))
171 CHIP_DBG(KERN_ERR "\tIPC Csum Error/Giant frame\n");
172
173 if (unlikely(p->des01.erx.late_collision)) {
174 CHIP_DBG(KERN_ERR "\tlate_collision error\n");
175 stats->collisions++;
176 stats->collisions++;
177 }
178 if (unlikely(p->des01.erx.receive_watchdog)) {
179 CHIP_DBG(KERN_ERR "\treceive_watchdog error\n");
180 x->rx_watchdog++;
181 }
182 if (unlikely(p->des01.erx.error_gmii)) {
183 CHIP_DBG(KERN_ERR "\tReceive Error\n");
184 x->rx_mii++;
185 }
186 if (unlikely(p->des01.erx.crc_error)) {
187 CHIP_DBG(KERN_ERR "\tCRC error\n");
188 x->rx_crc++;
189 stats->rx_crc_errors++;
190 }
191 ret = discard_frame;
192 }
193
194 /* After a payload csum error, the ES bit is set.
195 * It doesn't match with the information reported into the databook.
196 * At any rate, we need to understand if the CSUM hw computation is ok
197 * and report this info to the upper layers. */
198 ret = enh_desc_coe_rdes0(p->des01.erx.ipc_csum_error,
199 p->des01.erx.frame_type, p->des01.erx.payload_csum_error);
200
201 if (unlikely(p->des01.erx.dribbling)) {
202 CHIP_DBG(KERN_ERR "GMAC RX: dribbling error\n");
203 ret = discard_frame;
204 }
205 if (unlikely(p->des01.erx.sa_filter_fail)) {
206 CHIP_DBG(KERN_ERR "GMAC RX : Source Address filter fail\n");
207 x->sa_rx_filter_fail++;
208 ret = discard_frame;
209 }
210 if (unlikely(p->des01.erx.da_filter_fail)) {
211 CHIP_DBG(KERN_ERR "GMAC RX : Dest Address filter fail\n");
212 x->da_rx_filter_fail++;
213 ret = discard_frame;
214 }
215 if (unlikely(p->des01.erx.length_error)) {
216 CHIP_DBG(KERN_ERR "GMAC RX: length_error error\n");
217 x->rx_length++;
218 ret = discard_frame;
219 }
220#ifdef STMMAC_VLAN_TAG_USED
221 if (p->des01.erx.vlan_tag) {
222 CHIP_DBG(KERN_INFO "GMAC RX: VLAN frame tagged\n");
223 x->rx_vlan++;
224 }
225#endif
226 return ret;
227}
228
229static void enh_desc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
230 int disable_rx_ic)
231{
232 int i;
233 for (i = 0; i < ring_size; i++) {
234 p->des01.erx.own = 1;
235 p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
236 /* To support jumbo frames */
237 p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1;
238 if (i == ring_size - 1)
239 p->des01.erx.end_ring = 1;
240 if (disable_rx_ic)
241 p->des01.erx.disable_ic = 1;
242 p++;
243 }
244 return;
245}
246
247static void enh_desc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
248{
249 int i;
250
251 for (i = 0; i < ring_size; i++) {
252 p->des01.etx.own = 0;
253 if (i == ring_size - 1)
254 p->des01.etx.end_ring = 1;
255 p++;
256 }
257
258 return;
259}
260
261static int enh_desc_get_tx_owner(struct dma_desc *p)
262{
263 return p->des01.etx.own;
264}
265
266static int enh_desc_get_rx_owner(struct dma_desc *p)
267{
268 return p->des01.erx.own;
269}
270
271static void enh_desc_set_tx_owner(struct dma_desc *p)
272{
273 p->des01.etx.own = 1;
274}
275
276static void enh_desc_set_rx_owner(struct dma_desc *p)
277{
278 p->des01.erx.own = 1;
279}
280
281static int enh_desc_get_tx_ls(struct dma_desc *p)
282{
283 return p->des01.etx.last_segment;
284}
285
286static void enh_desc_release_tx_desc(struct dma_desc *p)
287{
288 int ter = p->des01.etx.end_ring;
289
290 memset(p, 0, sizeof(struct dma_desc));
291 p->des01.etx.end_ring = ter;
292
293 return;
294}
295
296static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
297 int csum_flag)
298{
299 p->des01.etx.first_segment = is_fs;
300 if (unlikely(len > BUF_SIZE_4KiB)) {
301 p->des01.etx.buffer1_size = BUF_SIZE_4KiB;
302 p->des01.etx.buffer2_size = len - BUF_SIZE_4KiB;
303 } else {
304 p->des01.etx.buffer1_size = len;
305 }
306 if (likely(csum_flag))
307 p->des01.etx.checksum_insertion = cic_full;
308}
309
310static void enh_desc_clear_tx_ic(struct dma_desc *p)
311{
312 p->des01.etx.interrupt = 0;
313}
314
315static void enh_desc_close_tx_desc(struct dma_desc *p)
316{
317 p->des01.etx.last_segment = 1;
318 p->des01.etx.interrupt = 1;
319}
320
321static int enh_desc_get_rx_frame_len(struct dma_desc *p)
322{
323 return p->des01.erx.frame_length;
324}
325
326struct stmmac_desc_ops enh_desc_ops = {
327 .tx_status = enh_desc_get_tx_status,
328 .rx_status = enh_desc_get_rx_status,
329 .get_tx_len = enh_desc_get_tx_len,
330 .init_rx_desc = enh_desc_init_rx_desc,
331 .init_tx_desc = enh_desc_init_tx_desc,
332 .get_tx_owner = enh_desc_get_tx_owner,
333 .get_rx_owner = enh_desc_get_rx_owner,
334 .release_tx_desc = enh_desc_release_tx_desc,
335 .prepare_tx_desc = enh_desc_prepare_tx_desc,
336 .clear_tx_ic = enh_desc_clear_tx_ic,
337 .close_tx_desc = enh_desc_close_tx_desc,
338 .get_tx_ls = enh_desc_get_tx_ls,
339 .set_tx_owner = enh_desc_set_tx_owner,
340 .set_rx_owner = enh_desc_set_rx_owner,
341 .get_rx_frame_len = enh_desc_get_rx_frame_len,
342};
diff --git a/drivers/net/stmmac/norm_desc.c b/drivers/net/stmmac/norm_desc.c
new file mode 100644
index 000000000000..ecfcc001a04a
--- /dev/null
+++ b/drivers/net/stmmac/norm_desc.c
@@ -0,0 +1,240 @@
1/*******************************************************************************
2 This contains the functions to handle the normal descriptors.
3
4 Copyright (C) 2007-2009 STMicroelectronics Ltd
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms and conditions of the GNU General Public License,
8 version 2, as published by the Free Software Foundation.
9
10 This program is distributed in the hope it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 more details.
14
15 You should have received a copy of the GNU General Public License along with
16 this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18
19 The full GNU General Public License is included in this distribution in
20 the file called "COPYING".
21
22 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
23*******************************************************************************/
24
25#include "common.h"
26
27static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
28 struct dma_desc *p, unsigned long ioaddr)
29{
30 int ret = 0;
31 struct net_device_stats *stats = (struct net_device_stats *)data;
32
33 if (unlikely(p->des01.tx.error_summary)) {
34 if (unlikely(p->des01.tx.underflow_error)) {
35 x->tx_underflow++;
36 stats->tx_fifo_errors++;
37 }
38 if (unlikely(p->des01.tx.no_carrier)) {
39 x->tx_carrier++;
40 stats->tx_carrier_errors++;
41 }
42 if (unlikely(p->des01.tx.loss_carrier)) {
43 x->tx_losscarrier++;
44 stats->tx_carrier_errors++;
45 }
46 if (unlikely((p->des01.tx.excessive_deferral) ||
47 (p->des01.tx.excessive_collisions) ||
48 (p->des01.tx.late_collision)))
49 stats->collisions += p->des01.tx.collision_count;
50 ret = -1;
51 }
52 if (unlikely(p->des01.tx.heartbeat_fail)) {
53 x->tx_heartbeat++;
54 stats->tx_heartbeat_errors++;
55 ret = -1;
56 }
57 if (unlikely(p->des01.tx.deferred))
58 x->tx_deferred++;
59
60 return ret;
61}
62
63static int ndesc_get_tx_len(struct dma_desc *p)
64{
65 return p->des01.tx.buffer1_size;
66}
67
68/* This function verifies if each incoming frame has some errors
69 * and, if required, updates the multicast statistics.
70 * In case of success, it returns csum_none becasue the device
71 * is not able to compute the csum in HW. */
72static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
73 struct dma_desc *p)
74{
75 int ret = csum_none;
76 struct net_device_stats *stats = (struct net_device_stats *)data;
77
78 if (unlikely(p->des01.rx.last_descriptor == 0)) {
79 pr_warning("ndesc Error: Oversized Ethernet "
80 "frame spanned multiple buffers\n");
81 stats->rx_length_errors++;
82 return discard_frame;
83 }
84
85 if (unlikely(p->des01.rx.error_summary)) {
86 if (unlikely(p->des01.rx.descriptor_error))
87 x->rx_desc++;
88 if (unlikely(p->des01.rx.partial_frame_error))
89 x->rx_partial++;
90 if (unlikely(p->des01.rx.run_frame))
91 x->rx_runt++;
92 if (unlikely(p->des01.rx.frame_too_long))
93 x->rx_toolong++;
94 if (unlikely(p->des01.rx.collision)) {
95 x->rx_collision++;
96 stats->collisions++;
97 }
98 if (unlikely(p->des01.rx.crc_error)) {
99 x->rx_crc++;
100 stats->rx_crc_errors++;
101 }
102 ret = discard_frame;
103 }
104 if (unlikely(p->des01.rx.dribbling))
105 ret = discard_frame;
106
107 if (unlikely(p->des01.rx.length_error)) {
108 x->rx_length++;
109 ret = discard_frame;
110 }
111 if (unlikely(p->des01.rx.mii_error)) {
112 x->rx_mii++;
113 ret = discard_frame;
114 }
115 if (p->des01.rx.multicast_frame) {
116 x->rx_multicast++;
117 stats->multicast++;
118 }
119 return ret;
120}
121
122static void ndesc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
123 int disable_rx_ic)
124{
125 int i;
126 for (i = 0; i < ring_size; i++) {
127 p->des01.rx.own = 1;
128 p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
129 if (i == ring_size - 1)
130 p->des01.rx.end_ring = 1;
131 if (disable_rx_ic)
132 p->des01.rx.disable_ic = 1;
133 p++;
134 }
135 return;
136}
137
138static void ndesc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
139{
140 int i;
141 for (i = 0; i < ring_size; i++) {
142 p->des01.tx.own = 0;
143 if (i == ring_size - 1)
144 p->des01.tx.end_ring = 1;
145 p++;
146 }
147 return;
148}
149
150static int ndesc_get_tx_owner(struct dma_desc *p)
151{
152 return p->des01.tx.own;
153}
154
155static int ndesc_get_rx_owner(struct dma_desc *p)
156{
157 return p->des01.rx.own;
158}
159
160static void ndesc_set_tx_owner(struct dma_desc *p)
161{
162 p->des01.tx.own = 1;
163}
164
165static void ndesc_set_rx_owner(struct dma_desc *p)
166{
167 p->des01.rx.own = 1;
168}
169
170static int ndesc_get_tx_ls(struct dma_desc *p)
171{
172 return p->des01.tx.last_segment;
173}
174
175static void ndesc_release_tx_desc(struct dma_desc *p)
176{
177 int ter = p->des01.tx.end_ring;
178
179 /* clean field used within the xmit */
180 p->des01.tx.first_segment = 0;
181 p->des01.tx.last_segment = 0;
182 p->des01.tx.buffer1_size = 0;
183
184 /* clean status reported */
185 p->des01.tx.error_summary = 0;
186 p->des01.tx.underflow_error = 0;
187 p->des01.tx.no_carrier = 0;
188 p->des01.tx.loss_carrier = 0;
189 p->des01.tx.excessive_deferral = 0;
190 p->des01.tx.excessive_collisions = 0;
191 p->des01.tx.late_collision = 0;
192 p->des01.tx.heartbeat_fail = 0;
193 p->des01.tx.deferred = 0;
194
195 /* set termination field */
196 p->des01.tx.end_ring = ter;
197
198 return;
199}
200
201static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
202 int csum_flag)
203{
204 p->des01.tx.first_segment = is_fs;
205 p->des01.tx.buffer1_size = len;
206}
207
208static void ndesc_clear_tx_ic(struct dma_desc *p)
209{
210 p->des01.tx.interrupt = 0;
211}
212
213static void ndesc_close_tx_desc(struct dma_desc *p)
214{
215 p->des01.tx.last_segment = 1;
216 p->des01.tx.interrupt = 1;
217}
218
219static int ndesc_get_rx_frame_len(struct dma_desc *p)
220{
221 return p->des01.rx.frame_length;
222}
223
224struct stmmac_desc_ops ndesc_ops = {
225 .tx_status = ndesc_get_tx_status,
226 .rx_status = ndesc_get_rx_status,
227 .get_tx_len = ndesc_get_tx_len,
228 .init_rx_desc = ndesc_init_rx_desc,
229 .init_tx_desc = ndesc_init_tx_desc,
230 .get_tx_owner = ndesc_get_tx_owner,
231 .get_rx_owner = ndesc_get_rx_owner,
232 .release_tx_desc = ndesc_release_tx_desc,
233 .prepare_tx_desc = ndesc_prepare_tx_desc,
234 .clear_tx_ic = ndesc_clear_tx_ic,
235 .close_tx_desc = ndesc_close_tx_desc,
236 .get_tx_ls = ndesc_get_tx_ls,
237 .set_tx_owner = ndesc_set_tx_owner,
238 .set_rx_owner = ndesc_set_rx_owner,
239 .get_rx_frame_len = ndesc_get_rx_frame_len,
240};
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index ba35e6943cf4..55b9acae82a1 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -120,3 +120,5 @@ static inline int stmmac_claim_resource(struct platform_device *pdev)
120extern int stmmac_mdio_unregister(struct net_device *ndev); 120extern int stmmac_mdio_unregister(struct net_device *ndev);
121extern int stmmac_mdio_register(struct net_device *ndev); 121extern int stmmac_mdio_register(struct net_device *ndev);
122extern void stmmac_set_ethtool_ops(struct net_device *netdev); 122extern void stmmac_set_ethtool_ops(struct net_device *netdev);
123extern struct stmmac_desc_ops enh_desc_ops;
124extern struct stmmac_desc_ops ndesc_ops;
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index cbe2404223d7..dfeea96f681a 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -1581,10 +1581,13 @@ static int stmmac_mac_device_setup(struct net_device *dev)
1581 1581
1582 struct mac_device_info *device; 1582 struct mac_device_info *device;
1583 1583
1584 if (priv->is_gmac) 1584 if (priv->is_gmac) {
1585 device = dwmac1000_setup(ioaddr); 1585 device = dwmac1000_setup(ioaddr);
1586 else 1586 device->desc = &enh_desc_ops;
1587 } else {
1587 device = dwmac100_setup(ioaddr); 1588 device = dwmac100_setup(ioaddr);
1589 device->desc = &ndesc_ops;
1590 }
1588 1591
1589 if (!device) 1592 if (!device)
1590 return -ENOMEM; 1593 return -ENOMEM;