Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux...
[linux-2.6] / drivers / net / wireless / hostap / hostap_download.c
1 static int prism2_enable_aux_port(struct net_device *dev, int enable)
2 {
3         u16 val, reg;
4         int i, tries;
5         unsigned long flags;
6         struct hostap_interface *iface;
7         local_info_t *local;
8
9         iface = netdev_priv(dev);
10         local = iface->local;
11
12         if (local->no_pri) {
13                 if (enable) {
14                         PDEBUG(DEBUG_EXTRA2, "%s: no PRI f/w - assuming Aux "
15                                "port is already enabled\n", dev->name);
16                 }
17                 return 0;
18         }
19
20         spin_lock_irqsave(&local->cmdlock, flags);
21
22         /* wait until busy bit is clear */
23         tries = HFA384X_CMD_BUSY_TIMEOUT;
24         while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) {
25                 tries--;
26                 udelay(1);
27         }
28         if (tries == 0) {
29                 reg = HFA384X_INW(HFA384X_CMD_OFF);
30                 spin_unlock_irqrestore(&local->cmdlock, flags);
31                 printk("%s: prism2_enable_aux_port - timeout - reg=0x%04x\n",
32                        dev->name, reg);
33                 return -ETIMEDOUT;
34         }
35
36         val = HFA384X_INW(HFA384X_CONTROL_OFF);
37
38         if (enable) {
39                 HFA384X_OUTW(HFA384X_AUX_MAGIC0, HFA384X_PARAM0_OFF);
40                 HFA384X_OUTW(HFA384X_AUX_MAGIC1, HFA384X_PARAM1_OFF);
41                 HFA384X_OUTW(HFA384X_AUX_MAGIC2, HFA384X_PARAM2_OFF);
42
43                 if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_DISABLED)
44                         printk("prism2_enable_aux_port: was not disabled!?\n");
45                 val &= ~HFA384X_AUX_PORT_MASK;
46                 val |= HFA384X_AUX_PORT_ENABLE;
47         } else {
48                 HFA384X_OUTW(0, HFA384X_PARAM0_OFF);
49                 HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
50                 HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
51
52                 if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_ENABLED)
53                         printk("prism2_enable_aux_port: was not enabled!?\n");
54                 val &= ~HFA384X_AUX_PORT_MASK;
55                 val |= HFA384X_AUX_PORT_DISABLE;
56         }
57         HFA384X_OUTW(val, HFA384X_CONTROL_OFF);
58
59         udelay(5);
60
61         i = 10000;
62         while (i > 0) {
63                 val = HFA384X_INW(HFA384X_CONTROL_OFF);
64                 val &= HFA384X_AUX_PORT_MASK;
65
66                 if ((enable && val == HFA384X_AUX_PORT_ENABLED) ||
67                     (!enable && val == HFA384X_AUX_PORT_DISABLED))
68                         break;
69
70                 udelay(10);
71                 i--;
72         }
73
74         spin_unlock_irqrestore(&local->cmdlock, flags);
75
76         if (i == 0) {
77                 printk("prism2_enable_aux_port(%d) timed out\n",
78                        enable);
79                 return -ETIMEDOUT;
80         }
81
82         return 0;
83 }
84
85
86 static int hfa384x_from_aux(struct net_device *dev, unsigned int addr, int len,
87                             void *buf)
88 {
89         u16 page, offset;
90         if (addr & 1 || len & 1)
91                 return -1;
92
93         page = addr >> 7;
94         offset = addr & 0x7f;
95
96         HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
97         HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
98
99         udelay(5);
100
101 #ifdef PRISM2_PCI
102         {
103                 __le16 *pos = (__le16 *) buf;
104                 while (len > 0) {
105                         *pos++ = HFA384X_INW_DATA(HFA384X_AUXDATA_OFF);
106                         len -= 2;
107                 }
108         }
109 #else /* PRISM2_PCI */
110         HFA384X_INSW(HFA384X_AUXDATA_OFF, buf, len / 2);
111 #endif /* PRISM2_PCI */
112
113         return 0;
114 }
115
116
117 static int hfa384x_to_aux(struct net_device *dev, unsigned int addr, int len,
118                           void *buf)
119 {
120         u16 page, offset;
121         if (addr & 1 || len & 1)
122                 return -1;
123
124         page = addr >> 7;
125         offset = addr & 0x7f;
126
127         HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
128         HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
129
130         udelay(5);
131
132 #ifdef PRISM2_PCI
133         {
134                 __le16 *pos = (__le16 *) buf;
135                 while (len > 0) {
136                         HFA384X_OUTW_DATA(*pos++, HFA384X_AUXDATA_OFF);
137                         len -= 2;
138                 }
139         }
140 #else /* PRISM2_PCI */
141         HFA384X_OUTSW(HFA384X_AUXDATA_OFF, buf, len / 2);
142 #endif /* PRISM2_PCI */
143
144         return 0;
145 }
146
147
148 static int prism2_pda_ok(u8 *buf)
149 {
150         __le16 *pda = (__le16 *) buf;
151         int pos;
152         u16 len, pdr;
153
154         if (buf[0] == 0xff && buf[1] == 0x00 && buf[2] == 0xff &&
155             buf[3] == 0x00)
156                 return 0;
157
158         pos = 0;
159         while (pos + 1 < PRISM2_PDA_SIZE / 2) {
160                 len = le16_to_cpu(pda[pos]);
161                 pdr = le16_to_cpu(pda[pos + 1]);
162                 if (len == 0 || pos + len > PRISM2_PDA_SIZE / 2)
163                         return 0;
164
165                 if (pdr == 0x0000 && len == 2) {
166                         /* PDA end found */
167                         return 1;
168                 }
169
170                 pos += len + 1;
171         }
172
173         return 0;
174 }
175
176
177 static int prism2_download_aux_dump(struct net_device *dev,
178                                      unsigned int addr, int len, u8 *buf)
179 {
180         int res;
181
182         prism2_enable_aux_port(dev, 1);
183         res = hfa384x_from_aux(dev, addr, len, buf);
184         prism2_enable_aux_port(dev, 0);
185         if (res)
186                 return -1;
187
188         return 0;
189 }
190
191
192 static u8 * prism2_read_pda(struct net_device *dev)
193 {
194         u8 *buf;
195         int res, i, found = 0;
196 #define NUM_PDA_ADDRS 4
197         unsigned int pda_addr[NUM_PDA_ADDRS] = {
198                 0x7f0000 /* others than HFA3841 */,
199                 0x3f0000 /* HFA3841 */,
200                 0x390000 /* apparently used in older cards */,
201                 0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */,
202         };
203
204         buf = kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
205         if (buf == NULL)
206                 return NULL;
207
208         /* Note: wlan card should be in initial state (just after init cmd)
209          * and no other operations should be performed concurrently. */
210
211         prism2_enable_aux_port(dev, 1);
212
213         for (i = 0; i < NUM_PDA_ADDRS; i++) {
214                 PDEBUG(DEBUG_EXTRA2, "%s: trying to read PDA from 0x%08x",
215                        dev->name, pda_addr[i]);
216                 res = hfa384x_from_aux(dev, pda_addr[i], PRISM2_PDA_SIZE, buf);
217                 if (res)
218                         continue;
219                 if (res == 0 && prism2_pda_ok(buf)) {
220                         PDEBUG2(DEBUG_EXTRA2, ": OK\n");
221                         found = 1;
222                         break;
223                 } else {
224                         PDEBUG2(DEBUG_EXTRA2, ": failed\n");
225                 }
226         }
227
228         prism2_enable_aux_port(dev, 0);
229
230         if (!found) {
231                 printk(KERN_DEBUG "%s: valid PDA not found\n", dev->name);
232                 kfree(buf);
233                 buf = NULL;
234         }
235
236         return buf;
237 }
238
239
240 static int prism2_download_volatile(local_info_t *local,
241                                     struct prism2_download_data *param)
242 {
243         struct net_device *dev = local->dev;
244         int ret = 0, i;
245         u16 param0, param1;
246
247         if (local->hw_downloading) {
248                 printk(KERN_WARNING "%s: Already downloading - aborting new "
249                        "request\n", dev->name);
250                 return -1;
251         }
252
253         local->hw_downloading = 1;
254         if (local->pri_only) {
255                 hfa384x_disable_interrupts(dev);
256         } else {
257                 prism2_hw_shutdown(dev, 0);
258
259                 if (prism2_hw_init(dev, 0)) {
260                         printk(KERN_WARNING "%s: Could not initialize card for"
261                                " download\n", dev->name);
262                         ret = -1;
263                         goto out;
264                 }
265         }
266
267         if (prism2_enable_aux_port(dev, 1)) {
268                 printk(KERN_WARNING "%s: Could not enable AUX port\n",
269                        dev->name);
270                 ret = -1;
271                 goto out;
272         }
273
274         param0 = param->start_addr & 0xffff;
275         param1 = param->start_addr >> 16;
276
277         HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
278         HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
279         if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
280                              (HFA384X_PROGMODE_ENABLE_VOLATILE << 8),
281                              param0)) {
282                 printk(KERN_WARNING "%s: Download command execution failed\n",
283                        dev->name);
284                 ret = -1;
285                 goto out;
286         }
287
288         for (i = 0; i < param->num_areas; i++) {
289                 PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
290                        dev->name, param->data[i].len, param->data[i].addr);
291                 if (hfa384x_to_aux(dev, param->data[i].addr,
292                                    param->data[i].len, param->data[i].data)) {
293                         printk(KERN_WARNING "%s: RAM download at 0x%08x "
294                                "(len=%d) failed\n", dev->name,
295                                param->data[i].addr, param->data[i].len);
296                         ret = -1;
297                         goto out;
298                 }
299         }
300
301         HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
302         HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
303         if (hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
304                                 (HFA384X_PROGMODE_DISABLE << 8), param0)) {
305                 printk(KERN_WARNING "%s: Download command execution failed\n",
306                        dev->name);
307                 ret = -1;
308                 goto out;
309         }
310         /* ProgMode disable causes the hardware to restart itself from the
311          * given starting address. Give hw some time and ACK command just in
312          * case restart did not happen. */
313         mdelay(5);
314         HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
315
316         if (prism2_enable_aux_port(dev, 0)) {
317                 printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
318                        dev->name);
319                 /* continue anyway.. restart should have taken care of this */
320         }
321
322         mdelay(5);
323         local->hw_downloading = 0;
324         if (prism2_hw_config(dev, 2)) {
325                 printk(KERN_WARNING "%s: Card configuration after RAM "
326                        "download failed\n", dev->name);
327                 ret = -1;
328                 goto out;
329         }
330
331  out:
332         local->hw_downloading = 0;
333         return ret;
334 }
335
336
337 static int prism2_enable_genesis(local_info_t *local, int hcr)
338 {
339         struct net_device *dev = local->dev;
340         u8 initseq[4] = { 0x00, 0xe1, 0xa1, 0xff };
341         u8 readbuf[4];
342
343         printk(KERN_DEBUG "%s: test Genesis mode with HCR 0x%02x\n",
344                dev->name, hcr);
345         local->func->cor_sreset(local);
346         hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
347         local->func->genesis_reset(local, hcr);
348
349         /* Readback test */
350         hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
351         hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
352         hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
353
354         if (memcmp(initseq, readbuf, sizeof(initseq)) == 0) {
355                 printk(KERN_DEBUG "Readback test succeeded, HCR 0x%02x\n",
356                        hcr);
357                 return 0;
358         } else {
359                 printk(KERN_DEBUG "Readback test failed, HCR 0x%02x "
360                        "write %02x %02x %02x %02x read %02x %02x %02x %02x\n",
361                        hcr, initseq[0], initseq[1], initseq[2], initseq[3],
362                        readbuf[0], readbuf[1], readbuf[2], readbuf[3]);
363                 return 1;
364         }
365 }
366
367
368 static int prism2_get_ram_size(local_info_t *local)
369 {
370         int ret;
371
372         /* Try to enable genesis mode; 0x1F for x8 SRAM or 0x0F for x16 SRAM */
373         if (prism2_enable_genesis(local, 0x1f) == 0)
374                 ret = 8;
375         else if (prism2_enable_genesis(local, 0x0f) == 0)
376                 ret = 16;
377         else
378                 ret = -1;
379
380         /* Disable genesis mode */
381         local->func->genesis_reset(local, ret == 16 ? 0x07 : 0x17);
382
383         return ret;
384 }
385
386
387 static int prism2_download_genesis(local_info_t *local,
388                                    struct prism2_download_data *param)
389 {
390         struct net_device *dev = local->dev;
391         int ram16 = 0, i;
392         int ret = 0;
393
394         if (local->hw_downloading) {
395                 printk(KERN_WARNING "%s: Already downloading - aborting new "
396                        "request\n", dev->name);
397                 return -EBUSY;
398         }
399
400         if (!local->func->genesis_reset || !local->func->cor_sreset) {
401                 printk(KERN_INFO "%s: Genesis mode downloading not supported "
402                        "with this hwmodel\n", dev->name);
403                 return -EOPNOTSUPP;
404         }
405
406         local->hw_downloading = 1;
407
408         if (prism2_enable_aux_port(dev, 1)) {
409                 printk(KERN_DEBUG "%s: failed to enable AUX port\n",
410                        dev->name);
411                 ret = -EIO;
412                 goto out;
413         }
414
415         if (local->sram_type == -1) {
416                 /* 0x1F for x8 SRAM or 0x0F for x16 SRAM */
417                 if (prism2_enable_genesis(local, 0x1f) == 0) {
418                         ram16 = 0;
419                         PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x8 "
420                                "SRAM\n", dev->name);
421                 } else if (prism2_enable_genesis(local, 0x0f) == 0) {
422                         ram16 = 1;
423                         PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x16 "
424                                "SRAM\n", dev->name);
425                 } else {
426                         printk(KERN_DEBUG "%s: Could not initiate genesis "
427                                "mode\n", dev->name);
428                         ret = -EIO;
429                         goto out;
430                 }
431         } else {
432                 if (prism2_enable_genesis(local, local->sram_type == 8 ?
433                                           0x1f : 0x0f)) {
434                         printk(KERN_DEBUG "%s: Failed to set Genesis "
435                                "mode (sram_type=%d)\n", dev->name,
436                                local->sram_type);
437                         ret = -EIO;
438                         goto out;
439                 }
440                 ram16 = local->sram_type != 8;
441         }
442
443         for (i = 0; i < param->num_areas; i++) {
444                 PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
445                        dev->name, param->data[i].len, param->data[i].addr);
446                 if (hfa384x_to_aux(dev, param->data[i].addr,
447                                    param->data[i].len, param->data[i].data)) {
448                         printk(KERN_WARNING "%s: RAM download at 0x%08x "
449                                "(len=%d) failed\n", dev->name,
450                                param->data[i].addr, param->data[i].len);
451                         ret = -EIO;
452                         goto out;
453                 }
454         }
455
456         PDEBUG(DEBUG_EXTRA2, "Disable genesis mode\n");
457         local->func->genesis_reset(local, ram16 ? 0x07 : 0x17);
458         if (prism2_enable_aux_port(dev, 0)) {
459                 printk(KERN_DEBUG "%s: Failed to disable AUX port\n",
460                        dev->name);
461         }
462
463         mdelay(5);
464         local->hw_downloading = 0;
465
466         PDEBUG(DEBUG_EXTRA2, "Trying to initialize card\n");
467         /*
468          * Make sure the INIT command does not generate a command completion
469          * event by disabling interrupts.
470          */
471         hfa384x_disable_interrupts(dev);
472         if (prism2_hw_init(dev, 1)) {
473                 printk(KERN_DEBUG "%s: Initialization after genesis mode "
474                        "download failed\n", dev->name);
475                 ret = -EIO;
476                 goto out;
477         }
478
479         PDEBUG(DEBUG_EXTRA2, "Card initialized - running PRI only\n");
480         if (prism2_hw_init2(dev, 1)) {
481                 printk(KERN_DEBUG "%s: Initialization(2) after genesis mode "
482                        "download failed\n", dev->name);
483                 ret = -EIO;
484                 goto out;
485         }
486
487  out:
488         local->hw_downloading = 0;
489         return ret;
490 }
491
492
493 #ifdef PRISM2_NON_VOLATILE_DOWNLOAD
494 /* Note! Non-volatile downloading functionality has not yet been tested
495  * thoroughly and it may corrupt flash image and effectively kill the card that
496  * is being updated. You have been warned. */
497
498 static inline int prism2_download_block(struct net_device *dev,
499                                         u32 addr, u8 *data,
500                                         u32 bufaddr, int rest_len)
501 {
502         u16 param0, param1;
503         int block_len;
504
505         block_len = rest_len < 4096 ? rest_len : 4096;
506
507         param0 = addr & 0xffff;
508         param1 = addr >> 16;
509
510         HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF);
511         HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
512
513         if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
514                              (HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8),
515                              param0)) {
516                 printk(KERN_WARNING "%s: Flash download command execution "
517                        "failed\n", dev->name);
518                 return -1;
519         }
520
521         if (hfa384x_to_aux(dev, bufaddr, block_len, data)) {
522                 printk(KERN_WARNING "%s: flash download at 0x%08x "
523                        "(len=%d) failed\n", dev->name, addr, block_len);
524                 return -1;
525         }
526
527         HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
528         HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
529         if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
530                              (HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8),
531                              0)) {
532                 printk(KERN_WARNING "%s: Flash write command execution "
533                        "failed\n", dev->name);
534                 return -1;
535         }
536
537         return block_len;
538 }
539
540
541 static int prism2_download_nonvolatile(local_info_t *local,
542                                        struct prism2_download_data *dl)
543 {
544         struct net_device *dev = local->dev;
545         int ret = 0, i;
546         struct {
547                 __le16 page;
548                 __le16 offset;
549                 __le16 len;
550         } dlbuffer;
551         u32 bufaddr;
552
553         if (local->hw_downloading) {
554                 printk(KERN_WARNING "%s: Already downloading - aborting new "
555                        "request\n", dev->name);
556                 return -1;
557         }
558
559         ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER,
560                                    &dlbuffer, 6, 0);
561
562         if (ret < 0) {
563                 printk(KERN_WARNING "%s: Could not read download buffer "
564                        "parameters\n", dev->name);
565                 goto out;
566         }
567
568         printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
569                le16_to_cpu(dlbuffer.len),
570                le16_to_cpu(dlbuffer.page),
571                le16_to_cpu(dlbuffer.offset));
572
573         bufaddr = (le16_to_cpu(dlbuffer.page) << 7) + le16_to_cpu(dlbuffer.offset);
574
575         local->hw_downloading = 1;
576
577         if (!local->pri_only) {
578                 prism2_hw_shutdown(dev, 0);
579
580                 if (prism2_hw_init(dev, 0)) {
581                         printk(KERN_WARNING "%s: Could not initialize card for"
582                                " download\n", dev->name);
583                         ret = -1;
584                         goto out;
585                 }
586         }
587
588         hfa384x_disable_interrupts(dev);
589
590         if (prism2_enable_aux_port(dev, 1)) {
591                 printk(KERN_WARNING "%s: Could not enable AUX port\n",
592                        dev->name);
593                 ret = -1;
594                 goto out;
595         }
596
597         printk(KERN_DEBUG "%s: starting flash download\n", dev->name);
598         for (i = 0; i < dl->num_areas; i++) {
599                 int rest_len = dl->data[i].len;
600                 int data_off = 0;
601
602                 while (rest_len > 0) {
603                         int block_len;
604
605                         block_len = prism2_download_block(
606                                 dev, dl->data[i].addr + data_off,
607                                 dl->data[i].data + data_off, bufaddr,
608                                 rest_len);
609
610                         if (block_len < 0) {
611                                 ret = -1;
612                                 goto out;
613                         }
614
615                         rest_len -= block_len;
616                         data_off += block_len;
617                 }
618         }
619
620         HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
621         HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
622         if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
623                                 (HFA384X_PROGMODE_DISABLE << 8), 0)) {
624                 printk(KERN_WARNING "%s: Download command execution failed\n",
625                        dev->name);
626                 ret = -1;
627                 goto out;
628         }
629
630         if (prism2_enable_aux_port(dev, 0)) {
631                 printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
632                        dev->name);
633                 /* continue anyway.. restart should have taken care of this */
634         }
635
636         mdelay(5);
637
638         local->func->hw_reset(dev);
639         local->hw_downloading = 0;
640         if (prism2_hw_config(dev, 2)) {
641                 printk(KERN_WARNING "%s: Card configuration after flash "
642                        "download failed\n", dev->name);
643                 ret = -1;
644         } else {
645                 printk(KERN_INFO "%s: Card initialized successfully after "
646                        "flash download\n", dev->name);
647         }
648
649  out:
650         local->hw_downloading = 0;
651         return ret;
652 }
653 #endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
654
655
656 static void prism2_download_free_data(struct prism2_download_data *dl)
657 {
658         int i;
659
660         if (dl == NULL)
661                 return;
662
663         for (i = 0; i < dl->num_areas; i++)
664                 kfree(dl->data[i].data);
665         kfree(dl);
666 }
667
668
669 static int prism2_download(local_info_t *local,
670                            struct prism2_download_param *param)
671 {
672         int ret = 0;
673         int i;
674         u32 total_len = 0;
675         struct prism2_download_data *dl = NULL;
676
677         printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x "
678                "num_areas=%d\n",
679                param->dl_cmd, param->start_addr, param->num_areas);
680
681         if (param->num_areas > 100) {
682                 ret = -EINVAL;
683                 goto out;
684         }
685
686         dl = kzalloc(sizeof(*dl) + param->num_areas *
687                      sizeof(struct prism2_download_data_area), GFP_KERNEL);
688         if (dl == NULL) {
689                 ret = -ENOMEM;
690                 goto out;
691         }
692         dl->dl_cmd = param->dl_cmd;
693         dl->start_addr = param->start_addr;
694         dl->num_areas = param->num_areas;
695         for (i = 0; i < param->num_areas; i++) {
696                 PDEBUG(DEBUG_EXTRA2,
697                        "  area %d: addr=0x%08x len=%d ptr=0x%p\n",
698                        i, param->data[i].addr, param->data[i].len,
699                        param->data[i].ptr);
700
701                 dl->data[i].addr = param->data[i].addr;
702                 dl->data[i].len = param->data[i].len;
703
704                 total_len += param->data[i].len;
705                 if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN ||
706                     total_len > PRISM2_MAX_DOWNLOAD_LEN) {
707                         ret = -E2BIG;
708                         goto out;
709                 }
710
711                 dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL);
712                 if (dl->data[i].data == NULL) {
713                         ret = -ENOMEM;
714                         goto out;
715                 }
716
717                 if (copy_from_user(dl->data[i].data, param->data[i].ptr,
718                                    param->data[i].len)) {
719                         ret = -EFAULT;
720                         goto out;
721                 }
722         }
723
724         switch (param->dl_cmd) {
725         case PRISM2_DOWNLOAD_VOLATILE:
726         case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT:
727                 ret = prism2_download_volatile(local, dl);
728                 break;
729         case PRISM2_DOWNLOAD_VOLATILE_GENESIS:
730         case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT:
731                 ret = prism2_download_genesis(local, dl);
732                 break;
733         case PRISM2_DOWNLOAD_NON_VOLATILE:
734 #ifdef PRISM2_NON_VOLATILE_DOWNLOAD
735                 ret = prism2_download_nonvolatile(local, dl);
736 #else /* PRISM2_NON_VOLATILE_DOWNLOAD */
737                 printk(KERN_INFO "%s: non-volatile downloading not enabled\n",
738                        local->dev->name);
739                 ret = -EOPNOTSUPP;
740 #endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
741                 break;
742         default:
743                 printk(KERN_DEBUG "%s: unsupported download command %d\n",
744                        local->dev->name, param->dl_cmd);
745                 ret = -EINVAL;
746                 break;
747         };
748
749  out:
750         if (ret == 0 && dl &&
751             param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) {
752                 prism2_download_free_data(local->dl_pri);
753                 local->dl_pri = dl;
754         } else if (ret == 0 && dl &&
755                    param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) {
756                 prism2_download_free_data(local->dl_sec);
757                 local->dl_sec = dl;
758         } else
759                 prism2_download_free_data(dl);
760
761         return ret;
762 }