]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/net/stmmac/dwmac1000_dma.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[mirror_ubuntu-zesty-kernel.git] / drivers / net / stmmac / dwmac1000_dma.c
CommitLineData
47dd7a54
GC
1/*******************************************************************************
2 This is the driver for the GMAC on-chip Ethernet controller for ST SoCs.
3 DWC Ether MAC 10/100/1000 Universal version 3.41a has been used for
4 developing this code.
5
21d437cc
GC
6 This contains the functions to handle the dma and descriptors.
7
47dd7a54
GC
8 Copyright (C) 2007-2009 STMicroelectronics Ltd
9
10 This program is free software; you can redistribute it and/or modify it
11 under the terms and conditions of the GNU General Public License,
12 version 2, as published by the Free Software Foundation.
13
14 This program is distributed in the hope it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 more details.
18
19 You should have received a copy of the GNU General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc.,
21 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
22
23 The full GNU General Public License is included in this distribution in
24 the file called "COPYING".
25
26 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
27*******************************************************************************/
28
21d437cc 29#include "dwmac1000.h"
aec7ff27 30#include "dwmac_dma.h"
47dd7a54 31
21d437cc
GC
32static int dwmac1000_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx,
33 u32 dma_rx)
47dd7a54
GC
34{
35 u32 value = readl(ioaddr + DMA_BUS_MODE);
36 /* DMA SW reset */
37 value |= DMA_BUS_MODE_SFT_RESET;
38 writel(value, ioaddr + DMA_BUS_MODE);
39 do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET));
40
41 value = /* DMA_BUS_MODE_FB | */ DMA_BUS_MODE_4PBL |
42 ((pbl << DMA_BUS_MODE_PBL_SHIFT) |
43 (pbl << DMA_BUS_MODE_RPBL_SHIFT));
44
45#ifdef CONFIG_STMMAC_DA
46 value |= DMA_BUS_MODE_DA; /* Rx has priority over tx */
47#endif
48 writel(value, ioaddr + DMA_BUS_MODE);
49
50 /* Mask interrupts by writing to CSR7 */
51 writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
52
53 /* The base address of the RX/TX descriptor lists must be written into
54 * DMA CSR3 and CSR4, respectively. */
55 writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR);
56 writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR);
57
58 return 0;
59}
60
61/* Transmit FIFO flush operation */
21d437cc 62static void dwmac1000_flush_tx_fifo(unsigned long ioaddr)
47dd7a54
GC
63{
64 u32 csr6 = readl(ioaddr + DMA_CONTROL);
65 writel((csr6 | DMA_CONTROL_FTF), ioaddr + DMA_CONTROL);
66
67 do {} while ((readl(ioaddr + DMA_CONTROL) & DMA_CONTROL_FTF));
68}
69
21d437cc 70static void dwmac1000_dma_operation_mode(unsigned long ioaddr, int txmode,
47dd7a54
GC
71 int rxmode)
72{
73 u32 csr6 = readl(ioaddr + DMA_CONTROL);
74
75 if (txmode == SF_DMA_MODE) {
76 DBG(KERN_DEBUG "GMAC: enabling TX store and forward mode\n");
77 /* Transmit COE type 2 cannot be done in cut-through mode. */
78 csr6 |= DMA_CONTROL_TSF;
79 /* Operating on second frame increase the performance
80 * especially when transmit store-and-forward is used.*/
81 csr6 |= DMA_CONTROL_OSF;
82 } else {
83 DBG(KERN_DEBUG "GMAC: disabling TX store and forward mode"
84 " (threshold = %d)\n", txmode);
85 csr6 &= ~DMA_CONTROL_TSF;
86 csr6 &= DMA_CONTROL_TC_TX_MASK;
af901ca1 87 /* Set the transmit threshold */
47dd7a54
GC
88 if (txmode <= 32)
89 csr6 |= DMA_CONTROL_TTC_32;
90 else if (txmode <= 64)
91 csr6 |= DMA_CONTROL_TTC_64;
92 else if (txmode <= 128)
93 csr6 |= DMA_CONTROL_TTC_128;
94 else if (txmode <= 192)
95 csr6 |= DMA_CONTROL_TTC_192;
96 else
97 csr6 |= DMA_CONTROL_TTC_256;
98 }
99
100 if (rxmode == SF_DMA_MODE) {
101 DBG(KERN_DEBUG "GMAC: enabling RX store and forward mode\n");
102 csr6 |= DMA_CONTROL_RSF;
103 } else {
104 DBG(KERN_DEBUG "GMAC: disabling RX store and forward mode"
105 " (threshold = %d)\n", rxmode);
106 csr6 &= ~DMA_CONTROL_RSF;
107 csr6 &= DMA_CONTROL_TC_RX_MASK;
108 if (rxmode <= 32)
109 csr6 |= DMA_CONTROL_RTC_32;
110 else if (rxmode <= 64)
111 csr6 |= DMA_CONTROL_RTC_64;
112 else if (rxmode <= 96)
113 csr6 |= DMA_CONTROL_RTC_96;
114 else
115 csr6 |= DMA_CONTROL_RTC_128;
116 }
117
118 writel(csr6, ioaddr + DMA_CONTROL);
119 return;
120}
121
122/* Not yet implemented --- no RMON module */
21d437cc
GC
123static void dwmac1000_dma_diagnostic_fr(void *data,
124 struct stmmac_extra_stats *x, unsigned long ioaddr)
47dd7a54
GC
125{
126 return;
127}
128
21d437cc 129static void dwmac1000_dump_dma_regs(unsigned long ioaddr)
47dd7a54
GC
130{
131 int i;
132 pr_info(" DMA registers\n");
133 for (i = 0; i < 22; i++) {
134 if ((i < 9) || (i > 17)) {
135 int offset = i * 4;
136 pr_err("\t Reg No. %d (offset 0x%x): 0x%08x\n", i,
137 (DMA_BUS_MODE + offset),
138 readl(ioaddr + DMA_BUS_MODE + offset));
139 }
140 }
141 return;
142}
143
21d437cc
GC
144static int dwmac1000_get_tx_frame_status(void *data,
145 struct stmmac_extra_stats *x,
146 struct dma_desc *p, unsigned long ioaddr)
47dd7a54
GC
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++;
21d437cc 161 dwmac1000_flush_tx_fifo(ioaddr);
47dd7a54
GC
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");
21d437cc 189 dwmac1000_flush_tx_fifo(ioaddr);
47dd7a54
GC
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++;
21d437cc 201 dwmac1000_flush_tx_fifo(ioaddr);
47dd7a54
GC
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
21d437cc 221static int dwmac1000_get_tx_len(struct dma_desc *p)
47dd7a54
GC
222{
223 return p->des01.etx.buffer1_size;
224}
225
21d437cc 226static int dwmac1000_coe_rdes0(int ipc_err, int type, int payload_err)
47dd7a54
GC
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 * ----------------------------------------------------------
1b924032 233 * 0 0 0 | IEEE 802.3 Type frame (length < 1536 octects)
47dd7a54
GC
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
21d437cc
GC
269static int dwmac1000_get_rx_frame_status(void *data,
270 struct stmmac_extra_stats *x, struct dma_desc *p)
47dd7a54
GC
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. */
21d437cc 315 ret = dwmac1000_coe_rdes0(p->des01.erx.ipc_csum_error,
47dd7a54
GC
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");
1b924032 334 x->rx_length++;
47dd7a54
GC
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
21d437cc 346static void dwmac1000_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
47dd7a54
GC
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
21d437cc 364static void dwmac1000_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
47dd7a54
GC
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
21d437cc 378static int dwmac1000_get_tx_owner(struct dma_desc *p)
47dd7a54
GC
379{
380 return p->des01.etx.own;
381}
382
21d437cc 383static int dwmac1000_get_rx_owner(struct dma_desc *p)
47dd7a54
GC
384{
385 return p->des01.erx.own;
386}
387
21d437cc 388static void dwmac1000_set_tx_owner(struct dma_desc *p)
47dd7a54
GC
389{
390 p->des01.etx.own = 1;
391}
392
21d437cc 393static void dwmac1000_set_rx_owner(struct dma_desc *p)
47dd7a54
GC
394{
395 p->des01.erx.own = 1;
396}
397
21d437cc 398static int dwmac1000_get_tx_ls(struct dma_desc *p)
47dd7a54
GC
399{
400 return p->des01.etx.last_segment;
401}
402
21d437cc 403static void dwmac1000_release_tx_desc(struct dma_desc *p)
47dd7a54
GC
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
21d437cc 413static void dwmac1000_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
47dd7a54
GC
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
21d437cc 427static void dwmac1000_clear_tx_ic(struct dma_desc *p)
47dd7a54
GC
428{
429 p->des01.etx.interrupt = 0;
430}
431
21d437cc 432static void dwmac1000_close_tx_desc(struct dma_desc *p)
47dd7a54
GC
433{
434 p->des01.etx.last_segment = 1;
435 p->des01.etx.interrupt = 1;
436}
437
21d437cc 438static int dwmac1000_get_rx_frame_len(struct dma_desc *p)
47dd7a54
GC
439{
440 return p->des01.erx.frame_length;
441}
442
21d437cc
GC
443struct stmmac_dma_ops dwmac1000_dma_ops = {
444 .init = dwmac1000_dma_init,
445 .dump_regs = dwmac1000_dump_dma_regs,
446 .dma_mode = dwmac1000_dma_operation_mode,
447 .dma_diagnostic_fr = dwmac1000_dma_diagnostic_fr,
aec7ff27
GC
448 .enable_dma_transmission = dwmac_enable_dma_transmission,
449 .enable_dma_irq = dwmac_enable_dma_irq,
450 .disable_dma_irq = dwmac_disable_dma_irq,
451 .start_tx = dwmac_dma_start_tx,
452 .stop_tx = dwmac_dma_stop_tx,
453 .start_rx = dwmac_dma_start_rx,
454 .stop_rx = dwmac_dma_stop_rx,
455 .dma_interrupt = dwmac_dma_interrupt,
db98a0b0
GC
456};
457
21d437cc
GC
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,
47dd7a54 474};