aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAndrey Borzenkov <arvidjaar@newmail.ru>2008-10-10 13:26:30 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-22 18:09:32 -0400
commit70458259936e723a4ac02c85bdbaf08dc69edfbe (patch)
tree0a39aff47887da2f3506430a4cb6799aa290d320 /drivers/net
parent8bdd5b9c6bd53add260756b6673a0545fbdbba21 (diff)
orinoco: reduce stack usage in firmware download path
orinoco_dl_firmware and symbol_dl_mage allocate large local variables (1K); at least orinoco fails with panic or hung kernel if 4K stacks is enabled. Allocate large buffers dynamically at run time. Tested-By: Andrey Borzenkov <arvidjaar@mail.ru> for Agere case Signed-off-by: Andrey Borzenkov < arvidjaar@mail.ru> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/orinoco.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 50904771f291..e0512e49d6d3 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -433,7 +433,7 @@ struct fw_info {
433const static struct fw_info orinoco_fw[] = { 433const static struct fw_info orinoco_fw[] = {
434 { "", "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 }, 434 { "", "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
435 { "", "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 }, 435 { "", "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
436 { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", "", 0x00003100, 0x100 } 436 { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", "", 0x00003100, 512 }
437}; 437};
438 438
439/* Structure used to access fields in FW 439/* Structure used to access fields in FW
@@ -458,7 +458,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
458 int ap) 458 int ap)
459{ 459{
460 /* Plug Data Area (PDA) */ 460 /* Plug Data Area (PDA) */
461 __le16 pda[512] = { 0 }; 461 __le16 *pda;
462 462
463 hermes_t *hw = &priv->hw; 463 hermes_t *hw = &priv->hw;
464 const struct firmware *fw_entry; 464 const struct firmware *fw_entry;
@@ -467,7 +467,11 @@ orinoco_dl_firmware(struct orinoco_private *priv,
467 const unsigned char *end; 467 const unsigned char *end;
468 const char *firmware; 468 const char *firmware;
469 struct net_device *dev = priv->ndev; 469 struct net_device *dev = priv->ndev;
470 int err; 470 int err = 0;
471
472 pda = kzalloc(fw->pda_size, GFP_KERNEL);
473 if (!pda)
474 return -ENOMEM;
471 475
472 if (ap) 476 if (ap)
473 firmware = fw->ap_fw; 477 firmware = fw->ap_fw;
@@ -478,17 +482,17 @@ orinoco_dl_firmware(struct orinoco_private *priv,
478 dev->name, firmware); 482 dev->name, firmware);
479 483
480 /* Read current plug data */ 484 /* Read current plug data */
481 err = hermes_read_pda(hw, pda, fw->pda_addr, 485 err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0);
482 min_t(u16, fw->pda_size, sizeof(pda)), 0);
483 printk(KERN_DEBUG "%s: Read PDA returned %d\n", dev->name, err); 486 printk(KERN_DEBUG "%s: Read PDA returned %d\n", dev->name, err);
484 if (err) 487 if (err)
485 return err; 488 goto free;
486 489
487 err = request_firmware(&fw_entry, firmware, priv->dev); 490 err = request_firmware(&fw_entry, firmware, priv->dev);
488 if (err) { 491 if (err) {
489 printk(KERN_ERR "%s: Cannot find firmware %s\n", 492 printk(KERN_ERR "%s: Cannot find firmware %s\n",
490 dev->name, firmware); 493 dev->name, firmware);
491 return -ENOENT; 494 err = -ENOENT;
495 goto free;
492 } 496 }
493 497
494 hdr = (const struct orinoco_fw_header *) fw_entry->data; 498 hdr = (const struct orinoco_fw_header *) fw_entry->data;
@@ -532,6 +536,9 @@ orinoco_dl_firmware(struct orinoco_private *priv,
532 536
533abort: 537abort:
534 release_firmware(fw_entry); 538 release_firmware(fw_entry);
539
540free:
541 kfree(pda);
535 return err; 542 return err;
536} 543}
537 544
@@ -549,12 +556,12 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
549 int secondary) 556 int secondary)
550{ 557{
551 hermes_t *hw = &priv->hw; 558 hermes_t *hw = &priv->hw;
552 int ret; 559 int ret = 0;
553 const unsigned char *ptr; 560 const unsigned char *ptr;
554 const unsigned char *first_block; 561 const unsigned char *first_block;
555 562
556 /* Plug Data Area (PDA) */ 563 /* Plug Data Area (PDA) */
557 __le16 pda[256]; 564 __le16 *pda = NULL;
558 565
559 /* Binary block begins after the 0x1A marker */ 566 /* Binary block begins after the 0x1A marker */
560 ptr = image; 567 ptr = image;
@@ -563,28 +570,33 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
563 570
564 /* Read the PDA from EEPROM */ 571 /* Read the PDA from EEPROM */
565 if (secondary) { 572 if (secondary) {
566 ret = hermes_read_pda(hw, pda, fw->pda_addr, sizeof(pda), 1); 573 pda = kzalloc(fw->pda_size, GFP_KERNEL);
574 if (!pda)
575 return -ENOMEM;
576
577 ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1);
567 if (ret) 578 if (ret)
568 return ret; 579 goto free;
569 } 580 }
570 581
571 /* Stop the firmware, so that it can be safely rewritten */ 582 /* Stop the firmware, so that it can be safely rewritten */
572 if (priv->stop_fw) { 583 if (priv->stop_fw) {
573 ret = priv->stop_fw(priv, 1); 584 ret = priv->stop_fw(priv, 1);
574 if (ret) 585 if (ret)
575 return ret; 586 goto free;
576 } 587 }
577 588
578 /* Program the adapter with new firmware */ 589 /* Program the adapter with new firmware */
579 ret = hermes_program(hw, first_block, end); 590 ret = hermes_program(hw, first_block, end);
580 if (ret) 591 if (ret)
581 return ret; 592 goto free;
582 593
583 /* Write the PDA to the adapter */ 594 /* Write the PDA to the adapter */
584 if (secondary) { 595 if (secondary) {
585 size_t len = hermes_blocks_length(first_block); 596 size_t len = hermes_blocks_length(first_block);
586 ptr = first_block + len; 597 ptr = first_block + len;
587 ret = hermes_apply_pda(hw, ptr, pda); 598 ret = hermes_apply_pda(hw, ptr, pda);
599 kfree(pda);
588 if (ret) 600 if (ret)
589 return ret; 601 return ret;
590 } 602 }
@@ -608,6 +620,10 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
608 return -ENODEV; 620 return -ENODEV;
609 621
610 return 0; 622 return 0;
623
624free:
625 kfree(pda);
626 return ret;
611} 627}
612 628
613 629