Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 }
763 
  This page was automatically generated by the LXR engine.