clean up nfsd kernel config entries (#1523)
[openwrt.git] / target / linux / ixp4xx-2.6 / patches / 139-ixp4xx_net_driver_mtd_load_fw.patch
1 diff -Naupr a/drivers/net/ixp4xx/Kconfig b/drivers/net/ixp4xx/Kconfig
2 --- a/drivers/net/ixp4xx/Kconfig        2007-01-12 21:54:40.000000000 -0700
3 +++ b/drivers/net/ixp4xx/Kconfig        2007-01-12 23:28:50.000000000 -0700
4 @@ -11,6 +11,7 @@ config IXP4XX_NPE
5         tristate "IXP4xx NPE support"
6         depends on ARCH_IXP4XX
7         depends on NET_ETHERNET
8 +       select CRC16
9         help
10           The IXP4XX NPE driver supports the 3 CPU co-processors called
11           "Network Processing Engines" (NPE). It adds support fo downloading
12 @@ -18,7 +19,7 @@ config IXP4XX_NPE
13           More about this at: Documentation/networking/ixp4xx/README.
14           You can either use this OR the Intel Access Library (IAL)
15  
16 -config IXP4XX_FW_LOAD
17 +config IXP4XX_NPE_FW_LOAD
18         bool "Use Firmware hotplug for Microcode download"
19         depends on IXP4XX_NPE
20         select HOTPLUG
21 @@ -28,6 +29,13 @@ config IXP4XX_FW_LOAD
22           /usr/lib/hotplug/firmware/NPE-[ABC]
23           see Documentation/firmware_class/hotplug-script
24  
25 +config IXP4XX_NPE_FW_MTD
26 +       bool "Load firmware from an mtd partition"
27 +       depends on IXP4XX_NPE && MTD_IXP4XX
28 +       help
29 +         With this option, the driver will search for
30 +         the firmware into an MTD partition.
31 +
32  config IXP4XX_MAC
33         tristate "IXP4xx MAC support"
34         depends on IXP4XX_NPE
35 diff -Naupr a/drivers/net/ixp4xx/Makefile b/drivers/net/ixp4xx/Makefile
36 --- a/drivers/net/ixp4xx/Makefile       2007-01-12 21:54:40.000000000 -0700
37 +++ b/drivers/net/ixp4xx/Makefile       2007-01-12 23:28:50.000000000 -0700
38 @@ -1,5 +1,6 @@
39  obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o
40  obj-$(CONFIG_IXP4XX_NPE) += ixp4xx_npe.o
41 +obj-$(CONFIG_IXP4XX_NPE_FW_MTD) += npe_ucode.o
42  obj-$(CONFIG_IXP4XX_MAC) += ixp4xx_mac.o
43  obj-$(CONFIG_IXP4XX_CRYPTO) += ixp4xx_crypto.o
44  
45 diff -Naupr a/drivers/net/ixp4xx/npe_ucode.c b/drivers/net/ixp4xx/npe_ucode.c
46 --- a/drivers/net/ixp4xx/npe_ucode.c    1969-12-31 17:00:00.000000000 -0700
47 +++ b/drivers/net/ixp4xx/npe_ucode.c    2007-01-12 23:28:50.000000000 -0700
48 @@ -0,0 +1,185 @@
49 +/*
50 + * Provide an NPE platform device for microcode handling
51 + *
52 + * Copyright (C) 2006 Christian Hohnstaedt <chohnstaedt@innominate.com>
53 + *
54 + * This file is released under the GPLv2
55 + */
56 +
57 +#include <linux/kernel.h>
58 +#include <linux/platform_device.h>
59 +#include <linux/init.h>
60 +#include <linux/slab.h>
61 +#include <linux/firmware.h>
62 +#include <linux/mtd/mtd.h>
63 +
64 +#include <linux/ixp_npe.h>
65 +
66 +#define DL_MAGIC 0xfeedf00d
67 +#define DL_MAGIC_SWAP 0x0df0edfe
68 +
69 +#define IMG_SIZE(image) (((image)->size * sizeof(u32)) + \
70 +               sizeof(struct dl_image))
71 +
72 +#define IMG_REV_MAJOR(id) (((id) >> 8) & 0x0f)
73 +#define IMG_REV_MINOR(id) ((id) & 0x0f)
74 +#define IMG_FUNC(id) (((id) >> 16) & 0xff)
75 +#define IMG_NPE(id) (((id) >> 24) & 0x0f)
76 +#define IMG_IXP(id) (((id) >> 28) & 0x0f)
77 +
78 +static struct platform_driver ixp4xx_npe_ucode_driver;
79 +static unsigned char *partition_name = NULL;
80 +
81 +static void print_image_info(u32 id, u32 offset, u32 size)
82 +{
83 +       unsigned char idx;
84 +       const char *names[] = { "IXP425", "IXP465", "unknown" };
85 +
86 +       idx = IMG_IXP(id) < 2 ? IMG_IXP(id) : 2;
87 +
88 +       printk(KERN_INFO "npe: found at 0x%x, %s/NPE-%c func: %02x, rev: %x.%x, "
89 +               "size: %5d, id: %08x\n", offset, names[idx], IMG_NPE(id) + 'A',
90 +               IMG_FUNC(id), IMG_REV_MAJOR(id), IMG_REV_MINOR(id), size, id);
91 +}
92 +
93 +void npe_swap_image(struct dl_image *image)
94 +{
95 +       unsigned int i;
96 +
97 +       image->magic = swab32(image->magic);
98 +       image->id = swab32(image->id);
99 +       image->size = swab32(image->size);
100 +
101 +       for (i = 0; i < image->size; i++)
102 +               image->u.data[i] = swab32(image->u.data[i]);
103 +}
104 +
105 +static void npe_find_microcode(struct mtd_info *mtd)
106 +{
107 +       u32 buf;
108 +       u32 magic = htonl(DL_MAGIC);
109 +       u32 id, size;
110 +       size_t retlen;
111 +       int err;
112 +       unsigned int offset = 0;
113 +
114 +       printk("npe: searching for firmware...\n");
115 +
116 +       while (offset < mtd->size) {
117 +
118 +               err = mtd->read(mtd, offset, 4, &retlen, (u_char *) &buf);
119 +               offset += retlen;
120 +
121 +               if (buf != magic)
122 +                       continue;
123 +
124 +               err = mtd->read(mtd, offset, 4, &retlen, (u_char *) &id);
125 +               offset += retlen;
126 +
127 +               if (id == magic)
128 +                       break;
129 +
130 +               id = ntohl(id);
131 +
132 +               err = mtd->read(mtd, offset, 4, &retlen, (u_char *) &size);
133 +               offset += retlen;
134 +
135 +               size = (ntohl(size) * 4) + 12;
136 +
137 +               print_image_info(id, offset - 12, size);
138 +
139 +               if (size < 24000 && ( IMG_FUNC(id) == 0x01 || IMG_FUNC(id) == 0x00) ) { // XXX fix size/detection
140 +
141 +                       struct dl_image *image = kmalloc(size, GFP_KERNEL);
142 +
143 +                       /* we are going to load it, rewind offset */
144 +                       offset -= 12;
145 +
146 +                       if (image) {
147 +                               err = mtd->read(mtd, offset, size, &retlen, (u_char *) image);
148 +
149 +                               if (err == 0 && retlen == size) {
150 +                                       if (image->magic == DL_MAGIC_SWAP)
151 +                                               npe_swap_image(image);
152 +
153 +                                       store_npe_image(image, NULL);
154 +                               } else {
155 +                                       printk(KERN_ERR "unable to read firmware\n");
156 +                               }
157 +
158 +                               kfree(image);
159 +                       }
160 +
161 +                       offset += size;
162 +               }
163 +       }
164 +}
165 +
166 +static void npe_flash_add(struct mtd_info *mtd)
167 +{
168 +       if (partition_name == NULL)
169 +               return;
170 +
171 +       if (strcmp(mtd->name, partition_name) == 0) {
172 +               npe_find_microcode(mtd);
173 +       }
174 +}
175 +
176 +static void npe_flash_remove(struct mtd_info *mtd) {
177 +}
178 +
179 +static struct mtd_notifier npe_flash_notifier = {
180 +       .add = npe_flash_add,
181 +       .remove = npe_flash_remove,
182 +};
183 +
184 +static int npe_ucode_probe(struct platform_device *pdev)
185 +{
186 +       struct npe_ucode_platform_data *data = pdev->dev.platform_data;
187 +
188 +       if (partition_name)
189 +               return -EEXIST;
190 +
191 +       if (data && data->mtd_partition) {
192 +               partition_name = data->mtd_partition;
193 +               return 0;
194 +       }
195 +
196 +       return -EINVAL;
197 +}
198 +
199 +static int npe_ucode_remove(struct platform_device *pdev)
200 +{
201 +       return 0;
202 +}
203 +
204 +static struct platform_driver ixp4xx_npe_ucode_driver = {
205 +       .driver = {
206 +               .name   = "ixp4xx_npe_ucode",
207 +               .owner  = THIS_MODULE,
208 +       },
209 +       .probe  = npe_ucode_probe,
210 +       .remove = npe_ucode_remove,
211 +};
212 +
213 +static int __init npe_ucode_init(void)
214 +{
215 +       int ret;
216 +
217 +       ret = platform_driver_register(&ixp4xx_npe_ucode_driver);
218 +       register_mtd_user(&npe_flash_notifier);
219 +
220 +       return ret;
221 +}
222 +
223 +static void __exit npe_ucode_exit(void)
224 +{
225 +       unregister_mtd_user(&npe_flash_notifier);
226 +       platform_driver_unregister(&ixp4xx_npe_ucode_driver);
227 +}
228 +
229 +module_init(npe_ucode_init);
230 +module_exit(npe_ucode_exit);
231 +
232 +MODULE_LICENSE("GPL");
233 +MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
234 diff -Naupr a/drivers/net/ixp4xx/ucode_dl.c b/drivers/net/ixp4xx/ucode_dl.c
235 --- a/drivers/net/ixp4xx/ucode_dl.c     2007-01-12 21:54:40.000000000 -0700
236 +++ b/drivers/net/ixp4xx/ucode_dl.c     2007-01-12 23:28:50.000000000 -0700
237 @@ -16,6 +16,7 @@
238  #include <linux/firmware.h>
239  #include <linux/dma-mapping.h>
240  #include <linux/byteorder/swab.h>
241 +#include <linux/crc16.h>
242  #include <asm/uaccess.h>
243  #include <asm/io.h>
244  
245 @@ -26,6 +27,12 @@
246  #define DL_MAGIC 0xfeedf00d
247  #define DL_MAGIC_SWAP 0x0df0edfe
248  
249 +#define IMG_REV_MAJOR(id) (((id) >> 8) & 0x0f)
250 +#define IMG_REV_MINOR(id) ((id) & 0x0f)
251 +#define IMG_FUNC(id) (((id) >> 16) & 0xff)
252 +#define IMG_NPE(id) (((id) >> 24) & 0x0f)
253 +#define IMG_IXP(id) (((id) >> 28) & 0x0f)
254 +
255  #define EOF_BLOCK 0xf
256  #define IMG_SIZE(image) (((image)->size * sizeof(u32)) + \
257                 sizeof(struct dl_image))
258 @@ -38,21 +45,6 @@ enum blk_type {
259         data,
260  };
261  
262 -struct dl_block {
263 -       u32 type;
264 -       u32 offset;
265 -};
266 -
267 -struct dl_image {
268 -       u32 magic;
269 -       u32 id;
270 -       u32 size;
271 -       union {
272 -               u32 data[0];
273 -               struct dl_block block[0];
274 -       } u;
275 -};
276 -
277  struct dl_codeblock {
278         u32 npe_addr;
279         u32 size;
280 @@ -127,20 +119,33 @@ download_block(struct npe_info *npe, str
281         return 0;
282  }
283  
284 -static int store_npe_image(struct dl_image *image, struct device *dev)
285 +int store_npe_image(struct dl_image *image, struct device *dev)
286  {
287         struct dl_block *blk;
288         struct dl_codeblock *cb;
289         struct npe_info *npe;
290         int ret=0;
291 +       u16 crc;
292  
293         if (!dev) {
294 -               dev = get_npe_by_id( (image->id >> 24) & 0xf);
295 +               dev = get_npe_by_id(IMG_NPE(image->id));
296                 return_npe_dev(dev);
297         }
298         if (!dev)
299                 return -ENODEV;
300  
301 +       if (image->size > 24000) { // XXX fix max size
302 +               printk(KERN_ERR "npe: firmware too large\n");
303 +               return -EFBIG;
304 +       }
305 +
306 +       if (IMG_REV_MAJOR(image->id) != 2) {
307 +               printk(KERN_ERR "npe: only revision 2 is supported at this time\n");
308 +               return -EINVAL;
309 +       }
310 +
311 +       crc = crc16(0, (u8 *) image, IMG_SIZE(image));
312 +
313         npe = dev_get_drvdata(dev);
314         if (npe->loaded && (npe->usage > 0)) {
315                 printk(KERN_INFO "Cowardly refusing to reload an Image "
316 @@ -267,8 +272,7 @@ static ssize_t ucode_write(struct file *
317  
318  static void npe_firmware_probe(struct device *dev)
319  {
320 -#if (defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)) \
321 -       && defined(MODULE)
322 +#ifdef CONFIG_IXP4XX_NPE_FW_LOADER
323         const struct firmware *fw_entry;
324         struct npe_info *npe = dev_get_drvdata(dev);
325         struct dl_image *image;
326 @@ -477,3 +481,4 @@ MODULE_AUTHOR("Christian Hohnstaedt <cho
327  
328  EXPORT_SYMBOL(get_npe_by_id);
329  EXPORT_SYMBOL(return_npe_dev);
330 +EXPORT_SYMBOL(store_npe_image);
331 diff -Naupr a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h
332 --- a/include/asm-arm/arch-ixp4xx/platform.h    2007-01-12 21:54:40.000000000 -0700
333 +++ b/include/asm-arm/arch-ixp4xx/platform.h    2007-01-12 23:28:50.000000000 -0700
334 @@ -89,6 +89,21 @@ struct ixp4xx_i2c_pins {
335  
336  struct sys_timer;
337  
338 +struct dl_block {
339 +       u32 type;
340 +        u32 offset;
341 +};
342 +
343 +struct dl_image {
344 +       u32 magic;
345 +       u32 id;
346 +       u32 size;
347 +       union {
348 +               u32 data[0];
349 +               struct dl_block block[0];
350 +       } u;
351 +};
352 +
353  struct npe_plat_data {
354         const char *name;
355         int data_size;
356 @@ -108,6 +123,10 @@ struct mac_plat_info {
357  
358  };
359  
360 +struct npe_ucode_platform_data {
361 +       unsigned char *mtd_partition;
362 +};
363
364  /*
365   * Frequency of clock used for primary clocksource
366   */
367 diff -Naupr a/include/linux/ixp_npe.h b/include/linux/ixp_npe.h
368 --- a/include/linux/ixp_npe.h   2007-01-12 21:54:40.000000000 -0700
369 +++ b/include/linux/ixp_npe.h   2007-01-12 23:28:50.000000000 -0700
370 @@ -99,6 +99,7 @@ extern void npe_reset(struct npe_info *n
371  
372  extern struct device *get_npe_by_id(int id);
373  extern void return_npe_dev(struct device *dev);
374 +extern int store_npe_image(struct dl_image *image, struct device *dev);
375  
376  /* NPE Messages */
377  extern int