Root/target/linux/coldfire/patches/100-kernel-2.6.38-Fix-FEC-driver-bugs-for-MCF547x-MCF548x.patch

1From 92b8d976e58fe5e6eb97aedcaa46e80c924fbc04 Mon Sep 17 00:00:00 2001
2From: Wang Huan <wanghuan@zch06.freescale.net>
3Date: Mon, 5 Sep 2011 08:59:46 +0800
4Subject: [PATCH] Fix FEC driver bugs for MCF547x/MCF548x
5
6This patch fixed kernel panic during flood ping with huge packets.
7It also fixed the data integrity errors when running iozone on an
8NFSv3-mounted file system.
9
10Signed-off-by: Jason Jin <jason.jin@freescale.com>
11---
12 arch/m68k/include/asm/cf_548x_cacheflush.h | 45 ++++++++++++++++++++++++---
13 drivers/net/fec_m547x.c | 18 +++++-----
14 2 files changed, 49 insertions(+), 14 deletions(-)
15
16--- a/arch/m68k/include/asm/cf_548x_cacheflush.h
17+++ b/arch/m68k/include/asm/cf_548x_cacheflush.h
18@@ -27,8 +27,8 @@
19     unsigned long end_set; \
20                                 \
21     start_set = 0; \
22- end_set = (unsigned long)LAST_DCACHE_ADDR; \
23- \
24+ end_set = (unsigned long)LAST_ICACHE_ADDR; \
25+ asm("nop"); \
26     for (set = start_set; set <= end_set; set += (0x10 - 3)) {\
27         asm volatile("cpushl %%ic,(%0)\n" \
28         "\taddq%.l #1,%0\n" \
29@@ -48,7 +48,7 @@
30                                 \
31     start_set = 0; \
32     end_set = (unsigned long)LAST_DCACHE_ADDR; \
33- \
34+ asm("nop"); \
35     for (set = start_set; set <= end_set; set += (0x10 - 3)) { \
36         asm volatile("cpushl %%dc,(%0)\n" \
37         "\taddq%.l #1,%0\n" \
38@@ -68,7 +68,7 @@
39                             \
40     start_set = 0; \
41     end_set = (unsigned long)LAST_DCACHE_ADDR; \
42- \
43+ asm("nop"); \
44     for (set = start_set; set <= end_set; set += (0x10 - 3)) { \
45         asm volatile("cpushl %%bc,(%0)\n" \
46         "\taddq%.l #1,%0\n" \
47@@ -240,12 +240,47 @@ extern inline void flush_icache_range(un
48     }
49 }
50 
51+static inline void flush_dcache_range(unsigned long address,
52+ unsigned long endaddr)
53+{
54+ unsigned long set;
55+ unsigned long start_set;
56+ unsigned long end_set;
57+
58+ start_set = address & _DCACHE_SET_MASK;
59+ end_set = endaddr & _DCACHE_SET_MASK;
60+
61+ if (start_set > end_set) {
62+ /* from the begining to the lowest address */
63+ for (set = 0; set <= end_set; set += (0x10 - 3)) {
64+ asm volatile("cpushl %%dc,(%0)\n"
65+ "\taddq%.l #1,%0\n"
66+ "\tcpushl %%dc,(%0)\n"
67+ "\taddq%.l #1,%0\n"
68+ "\tcpushl %%dc,(%0)\n"
69+ "\taddq%.l #1,%0\n"
70+ "\tcpushl %%dc,(%0)" : "=a" (set) : "a" (set));
71+ }
72+ /* next loop will finish the cache ie pass the hole */
73+ end_set = LAST_ICACHE_ADDR;
74+ }
75+ for (set = start_set; set <= end_set; set += (0x10 - 3)) {
76+ asm volatile("cpushl %%dc,(%0)\n"
77+ "\taddq%.l #1,%0\n"
78+ "\tcpushl %%dc,(%0)\n"
79+ "\taddq%.l #1,%0\n"
80+ "\tcpushl %%dc,(%0)\n"
81+ "\taddq%.l #1,%0\n"
82+ "\tcpushl %%dc,(%0)" : "=a" (set) : "a" (set));
83+ }
84+}
85+
86 static inline void copy_to_user_page(struct vm_area_struct *vma,
87                      struct page *page, unsigned long vaddr,
88                      void *dst, void *src, int len)
89 {
90     memcpy(dst, src, len);
91- flush_icache_user_page(vma, page, vaddr, len);
92+ flush_dcache();
93 }
94 static inline void copy_from_user_page(struct vm_area_struct *vma,
95                        struct page *page, unsigned long vaddr,
96--- a/drivers/net/fec_m547x.c
97+++ b/drivers/net/fec_m547x.c
98@@ -34,7 +34,7 @@
99 #include <asm/m5485sram.h>
100 #include <asm/virtconvert.h>
101 #include <asm/irq.h>
102-
103+#include <asm/cf_cacheflush.h>
104 #include "fec_m547x.h"
105 
106 #ifdef CONFIG_FEC_548x_ENABLE_FEC2
107@@ -97,7 +97,7 @@ static void fec_interrupt_fec_rx_handler
108 static irqreturn_t fec_interrupt_handler(int irq, void *dev_id);
109 static void fec_interrupt_fec_tx_handler_fec0(void);
110 static void fec_interrupt_fec_rx_handler_fec0(void);
111-static void fec_interrupt_fec_reinit(unsigned long data);
112+static void fec_interrupt_fec_reinit(struct net_device *dev);
113 
114 /* default fec0 address */
115 unsigned char fec_mac_addr_fec0[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x50 };
116@@ -145,6 +145,7 @@ static int coldfire_fec_mdio_read(struct
117 #ifdef CONFIG_FEC_548x_SHARED_PHY
118     unsigned long base_addr = (unsigned long)FEC_BASE_ADDR_FEC0;
119 #else
120+ struct net_device *dev = bus->priv;
121     unsigned long base_addr = (unsigned long) dev->base_addr;
122 #endif
123     int tries = 100;
124@@ -179,6 +180,7 @@ static int coldfire_fec_mdio_write(struc
125 #ifdef CONFIG_FEC_548x_SHARED_PHY
126     unsigned long base_addr = (unsigned long)FEC_BASE_ADDR_FEC0;
127 #else
128+ struct net_device *dev = bus->priv;
129     unsigned long base_addr = (unsigned long) dev->base_addr;
130 #endif
131     int tries = 100;
132@@ -394,9 +396,6 @@ static int mcf547x_fec_open(struct net_d
133 
134     dma_connect(channel, (int) fp->fecpriv_interrupt_fec_tx_handler);
135 
136- /* init tasklet for controller reinitialization */
137- tasklet_init(&fp->fecpriv_tasklet_reinit,
138- fec_interrupt_fec_reinit, (unsigned long) dev);
139 
140     /* Reset FIFOs */
141     FEC_FECFRST(base_addr) |= FEC_SW_RST | FEC_RST_CTL;
142@@ -790,6 +789,8 @@ static int mcf547x_fec_start_xmit(struct
143 
144     /* flush data cache before initializing
145      * the descriptor and starting DMA */
146+ flush_dcache_range(virt_to_phys(data_aligned),
147+ virt_to_phys(data_aligned) + skb->len);
148 
149     spin_lock_irq(&fp->fecpriv_lock);
150 
151@@ -1308,7 +1309,7 @@ irqreturn_t fec_interrupt_handler(int ir
152         netif_stop_queue(dev);
153 
154         /* execute reinitialization as tasklet */
155- tasklet_schedule(&fp->fecpriv_tasklet_reinit);
156+ fec_interrupt_fec_reinit(dev);
157 
158         fp->fecpriv_stat.rx_dropped++;
159     }
160@@ -1343,10 +1344,9 @@ irqreturn_t fec_interrupt_handler(int ir
161 * when controller must be reinitialized.
162 *
163 *************************************************************************/
164-void fec_interrupt_fec_reinit(unsigned long data)
165+void fec_interrupt_fec_reinit(struct net_device *dev)
166 {
167     int i;
168- struct net_device *dev = (struct net_device *)data;
169     struct fec_priv *fp = netdev_priv(dev);
170     unsigned long base_addr = (unsigned long) dev->base_addr;
171 
172@@ -1385,7 +1385,7 @@ void fec_interrupt_fec_reinit(unsigned l
173     fp->fecpriv_current_tx = fp->fecpriv_next_tx = 0;
174 
175     /* flush entire data cache before restarting the DMA */
176-
177+ flush_dcache();
178     /* restart DMA from beginning */
179     MCD_startDma(fp->fecpriv_fec_rx_channel,
180              (char *) fp->fecpriv_rxdesc, 0,
181

Archive Download this file



interactive