xburst: remove support for old kernels
[openwrt.git] / target / linux / coldfire / patches / 100-kernel-2.6.38-Fix-FEC-driver-bugs-for-MCF547x-MCF548x.patch
1 From 92b8d976e58fe5e6eb97aedcaa46e80c924fbc04 Mon Sep 17 00:00:00 2001
2 From: Wang Huan <wanghuan@zch06.freescale.net>
3 Date: Mon, 5 Sep 2011 08:59:46 +0800
4 Subject: [PATCH] Fix FEC driver bugs for MCF547x/MCF548x
5
6 This patch fixed kernel panic during flood ping with huge packets.
7 It also fixed the data integrity errors when running iozone on an
8 NFSv3-mounted file system.
9
10 Signed-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,