linux/drivers/net/wireless/hostap/hostap_download.c
<<
>>
Prefs
   1static 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
  86static 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                u16 *pos = (u16 *) 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
 117static 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                u16 *pos = (u16 *) 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
 148static int prism2_pda_ok(u8 *buf)
 149{
 150        u16 *pda = (u16 *) 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
 177static 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
 192static 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
 240static 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
 337static 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
 368static 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
 387static 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
 498static 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
 541static 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                u16 page;
 548                u16 offset;
 549                u16 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        dlbuffer.page = le16_to_cpu(dlbuffer.page);
 569        dlbuffer.offset = le16_to_cpu(dlbuffer.offset);
 570        dlbuffer.len = le16_to_cpu(dlbuffer.len);
 571
 572        printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
 573               dlbuffer.len, dlbuffer.page, dlbuffer.offset);
 574
 575        bufaddr = (dlbuffer.page << 7) + dlbuffer.offset;
 576
 577        local->hw_downloading = 1;
 578
 579        if (!local->pri_only) {
 580                prism2_hw_shutdown(dev, 0);
 581
 582                if (prism2_hw_init(dev, 0)) {
 583                        printk(KERN_WARNING "%s: Could not initialize card for"
 584                               " download\n", dev->name);
 585                        ret = -1;
 586                        goto out;
 587                }
 588        }
 589
 590        hfa384x_disable_interrupts(dev);
 591
 592        if (prism2_enable_aux_port(dev, 1)) {
 593                printk(KERN_WARNING "%s: Could not enable AUX port\n",
 594                       dev->name);
 595                ret = -1;
 596                goto out;
 597        }
 598
 599        printk(KERN_DEBUG "%s: starting flash download\n", dev->name);
 600        for (i = 0; i < dl->num_areas; i++) {
 601                int rest_len = dl->data[i].len;
 602                int data_off = 0;
 603
 604                while (rest_len > 0) {
 605                        int block_len;
 606
 607                        block_len = prism2_download_block(
 608                                dev, dl->data[i].addr + data_off,
 609                                dl->data[i].data + data_off, bufaddr,
 610                                rest_len);
 611
 612                        if (block_len < 0) {
 613                                ret = -1;
 614                                goto out;
 615                        }
 616
 617                        rest_len -= block_len;
 618                        data_off += block_len;
 619                }
 620        }
 621
 622        HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
 623        HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
 624        if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
 625                                (HFA384X_PROGMODE_DISABLE << 8), 0)) {
 626                printk(KERN_WARNING "%s: Download command execution failed\n",
 627                       dev->name);
 628                ret = -1;
 629                goto out;
 630        }
 631
 632        if (prism2_enable_aux_port(dev, 0)) {
 633                printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
 634                       dev->name);
 635                /* continue anyway.. restart should have taken care of this */
 636        }
 637
 638        mdelay(5);
 639
 640        local->func->hw_reset(dev);
 641        local->hw_downloading = 0;
 642        if (prism2_hw_config(dev, 2)) {
 643                printk(KERN_WARNING "%s: Card configuration after flash "
 644                       "download failed\n", dev->name);
 645                ret = -1;
 646        } else {
 647                printk(KERN_INFO "%s: Card initialized successfully after "
 648                       "flash download\n", dev->name);
 649        }
 650
 651 out:
 652        local->hw_downloading = 0;
 653        return ret;
 654}
 655#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
 656
 657
 658static void prism2_download_free_data(struct prism2_download_data *dl)
 659{
 660        int i;
 661
 662        if (dl == NULL)
 663                return;
 664
 665        for (i = 0; i < dl->num_areas; i++)
 666                kfree(dl->data[i].data);
 667        kfree(dl);
 668}
 669
 670
 671static int prism2_download(local_info_t *local,
 672                           struct prism2_download_param *param)
 673{
 674        int ret = 0;
 675        int i;
 676        u32 total_len = 0;
 677        struct prism2_download_data *dl = NULL;
 678
 679        printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x "
 680               "num_areas=%d\n",
 681               param->dl_cmd, param->start_addr, param->num_areas);
 682
 683        if (param->num_areas > 100) {
 684                ret = -EINVAL;
 685                goto out;
 686        }
 687
 688        dl = kzalloc(sizeof(*dl) + param->num_areas *
 689                     sizeof(struct prism2_download_data_area), GFP_KERNEL);
 690        if (dl == NULL) {
 691                ret = -ENOMEM;
 692                goto out;
 693        }
 694        dl->dl_cmd = param->dl_cmd;
 695        dl->start_addr = param->start_addr;
 696        dl->num_areas = param->num_areas;
 697        for (i = 0; i < param->num_areas; i++) {
 698                PDEBUG(DEBUG_EXTRA2,
 699                       "  area %d: addr=0x%08x len=%d ptr=0x%p\n",
 700                       i, param->data[i].addr, param->data[i].len,
 701                       param->data[i].ptr);
 702
 703                dl->data[i].addr = param->data[i].addr;
 704                dl->data[i].len = param->data[i].len;
 705
 706                total_len += param->data[i].len;
 707                if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN ||
 708                    total_len > PRISM2_MAX_DOWNLOAD_LEN) {
 709                        ret = -E2BIG;
 710                        goto out;
 711                }
 712
 713                dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL);
 714                if (dl->data[i].data == NULL) {
 715                        ret = -ENOMEM;
 716                        goto out;
 717                }
 718
 719                if (copy_from_user(dl->data[i].data, param->data[i].ptr,
 720                                   param->data[i].len)) {
 721                        ret = -EFAULT;
 722                        goto out;
 723                }
 724        }
 725
 726        switch (param->dl_cmd) {
 727        case PRISM2_DOWNLOAD_VOLATILE:
 728        case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT:
 729                ret = prism2_download_volatile(local, dl);
 730                break;
 731        case PRISM2_DOWNLOAD_VOLATILE_GENESIS:
 732        case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT:
 733                ret = prism2_download_genesis(local, dl);
 734                break;
 735        case PRISM2_DOWNLOAD_NON_VOLATILE:
 736#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
 737                ret = prism2_download_nonvolatile(local, dl);
 738#else /* PRISM2_NON_VOLATILE_DOWNLOAD */
 739                printk(KERN_INFO "%s: non-volatile downloading not enabled\n",
 740                       local->dev->name);
 741                ret = -EOPNOTSUPP;
 742#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
 743                break;
 744        default:
 745                printk(KERN_DEBUG "%s: unsupported download command %d\n",
 746                       local->dev->name, param->dl_cmd);
 747                ret = -EINVAL;
 748                break;
 749        };
 750
 751 out:
 752        if (ret == 0 && dl &&
 753            param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) {
 754                prism2_download_free_data(local->dl_pri);
 755                local->dl_pri = dl;
 756        } else if (ret == 0 && dl &&
 757                   param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) {
 758                prism2_download_free_data(local->dl_sec);
 759                local->dl_sec = dl;
 760        } else
 761                prism2_download_free_data(dl);
 762
 763        return ret;
 764}
 765