aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;