aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h52
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c46
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h1
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c687
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.h3
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c70
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.c28
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.c5
8 files changed, 565 insertions, 327 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index ee6571ed706d..c6ee1e974c84 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -504,6 +504,12 @@ struct bcm43xx_phyinfo {
504 * This lock is only used by bcm43xx_phy_{un}lock() 504 * This lock is only used by bcm43xx_phy_{un}lock()
505 */ 505 */
506 spinlock_t lock; 506 spinlock_t lock;
507
508 /* Firmware. */
509 const struct firmware *ucode;
510 const struct firmware *pcm;
511 const struct firmware *initvals0;
512 const struct firmware *initvals1;
507}; 513};
508 514
509 515
@@ -593,12 +599,14 @@ struct bcm43xx_coreinfo {
593 u8 available:1, 599 u8 available:1,
594 enabled:1, 600 enabled:1,
595 initialized:1; 601 initialized:1;
596 /** core_id ID number */
597 u16 id;
598 /** core_rev revision number */ 602 /** core_rev revision number */
599 u8 rev; 603 u8 rev;
600 /** Index number for _switch_core() */ 604 /** Index number for _switch_core() */
601 u8 index; 605 u8 index;
606 /** core_id ID number */
607 u16 id;
608 /** Core-specific data. */
609 void *priv;
602}; 610};
603 611
604/* Additional information for each 80211 core. */ 612/* Additional information for each 80211 core. */
@@ -647,7 +655,10 @@ enum {
647 BCM43xx_STAT_RESTARTING, /* controller_restart() called. */ 655 BCM43xx_STAT_RESTARTING, /* controller_restart() called. */
648}; 656};
649#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status) 657#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status)
650#define bcm43xx_set_status(bcm, stat) atomic_set(&(bcm)->init_status, (stat)) 658#define bcm43xx_set_status(bcm, stat) do { \
659 atomic_set(&(bcm)->init_status, (stat)); \
660 smp_wmb(); \
661 } while (0)
651 662
652/* *** THEORY OF LOCKING *** 663/* *** THEORY OF LOCKING ***
653 * 664 *
@@ -721,10 +732,6 @@ struct bcm43xx_private {
721 struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ]; 732 struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
722 /* Additional information, specific to the 80211 cores. */ 733 /* Additional information, specific to the 80211 cores. */
723 struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ]; 734 struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
724 /* Index of the current 80211 core. If current_core is not
725 * an 80211 core, this is -1.
726 */
727 int current_80211_core_idx;
728 /* Number of available 80211 cores. */ 735 /* Number of available 80211 cores. */
729 int nr_80211_available; 736 int nr_80211_available;
730 737
@@ -737,6 +744,8 @@ struct bcm43xx_private {
737 u32 irq_savedstate; 744 u32 irq_savedstate;
738 /* Link Quality calculation context. */ 745 /* Link Quality calculation context. */
739 struct bcm43xx_noise_calculation noisecalc; 746 struct bcm43xx_noise_calculation noisecalc;
747 /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
748 int mac_suspended;
740 749
741 /* Threshold values. */ 750 /* Threshold values. */
742 //TODO: The RTS thr has to be _used_. Currently, it is only set via WX. 751 //TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
@@ -759,12 +768,6 @@ struct bcm43xx_private {
759 struct bcm43xx_key key[54]; 768 struct bcm43xx_key key[54];
760 u8 default_key_idx; 769 u8 default_key_idx;
761 770
762 /* Firmware. */
763 const struct firmware *ucode;
764 const struct firmware *pcm;
765 const struct firmware *initvals0;
766 const struct firmware *initvals1;
767
768 /* Random Number Generator. */ 771 /* Random Number Generator. */
769 struct hwrng rng; 772 struct hwrng rng;
770 char rng_name[20 + 1]; 773 char rng_name[20 + 1];
@@ -827,34 +830,33 @@ int bcm43xx_using_pio(struct bcm43xx_private *bcm)
827 * any of these functions. 830 * any of these functions.
828 */ 831 */
829static inline 832static inline
833struct bcm43xx_coreinfo_80211 *
834bcm43xx_current_80211_priv(struct bcm43xx_private *bcm)
835{
836 assert(bcm->current_core->id == BCM43xx_COREID_80211);
837 return bcm->current_core->priv;
838}
839static inline
830struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm) 840struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
831{ 841{
832 assert(bcm43xx_using_pio(bcm)); 842 assert(bcm43xx_using_pio(bcm));
833 assert(bcm->current_80211_core_idx >= 0); 843 return &(bcm43xx_current_80211_priv(bcm)->pio);
834 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
835 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio);
836} 844}
837static inline 845static inline
838struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm) 846struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
839{ 847{
840 assert(!bcm43xx_using_pio(bcm)); 848 assert(!bcm43xx_using_pio(bcm));
841 assert(bcm->current_80211_core_idx >= 0); 849 return &(bcm43xx_current_80211_priv(bcm)->dma);
842 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
843 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma);
844} 850}
845static inline 851static inline
846struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm) 852struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
847{ 853{
848 assert(bcm->current_80211_core_idx >= 0); 854 return &(bcm43xx_current_80211_priv(bcm)->phy);
849 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
850 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy);
851} 855}
852static inline 856static inline
853struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm) 857struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
854{ 858{
855 assert(bcm->current_80211_core_idx >= 0); 859 return &(bcm43xx_current_80211_priv(bcm)->radio);
856 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
857 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
858} 860}
859 861
860 862
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
index 2600ee4b803a..923275ea0789 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -316,6 +316,42 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
316 return res; 316 return res;
317} 317}
318 318
319static ssize_t restart_write_file(struct file *file, const char __user *user_buf,
320 size_t count, loff_t *ppos)
321{
322 struct bcm43xx_private *bcm = file->private_data;
323 char *buf = really_big_buffer;
324 ssize_t buf_size;
325 ssize_t res;
326 unsigned long flags;
327
328 buf_size = min(count, sizeof (really_big_buffer) - 1);
329 down(&big_buffer_sem);
330 if (copy_from_user(buf, user_buf, buf_size)) {
331 res = -EFAULT;
332 goto out_up;
333 }
334 mutex_lock(&(bcm)->mutex);
335 spin_lock_irqsave(&(bcm)->irq_lock, flags);
336 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
337 printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
338 res = -EFAULT;
339 goto out_unlock;
340 }
341 if (count > 0 && buf[0] == '1') {
342 bcm43xx_controller_restart(bcm, "manually restarted");
343 res = count;
344 } else
345 res = -EINVAL;
346
347out_unlock:
348 spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
349 mutex_unlock(&(bcm)->mutex);
350out_up:
351 up(&big_buffer_sem);
352 return res;
353}
354
319#undef fappend 355#undef fappend
320 356
321 357
@@ -349,6 +385,11 @@ static struct file_operations txstat_fops = {
349 .open = open_file_generic, 385 .open = open_file_generic,
350}; 386};
351 387
388static struct file_operations restart_fops = {
389 .write = restart_write_file,
390 .open = open_file_generic,
391};
392
352 393
353void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) 394void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
354{ 395{
@@ -400,6 +441,10 @@ void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
400 bcm, &txstat_fops); 441 bcm, &txstat_fops);
401 if (!e->dentry_txstat) 442 if (!e->dentry_txstat)
402 printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir); 443 printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
444 e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir,
445 bcm, &restart_fops);
446 if (!e->dentry_restart)
447 printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir);
403} 448}
404 449
405void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) 450void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
@@ -415,6 +460,7 @@ void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
415 debugfs_remove(e->dentry_devinfo); 460 debugfs_remove(e->dentry_devinfo);
416 debugfs_remove(e->dentry_tsf); 461 debugfs_remove(e->dentry_tsf);
417 debugfs_remove(e->dentry_txstat); 462 debugfs_remove(e->dentry_txstat);
463 debugfs_remove(e->dentry_restart);
418 debugfs_remove(e->subdir); 464 debugfs_remove(e->subdir);
419 kfree(e->xmitstatus_buffer); 465 kfree(e->xmitstatus_buffer);
420 kfree(e->xmitstatus_print_buffer); 466 kfree(e->xmitstatus_print_buffer);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
index 50ce267f794d..a40d1af35545 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
@@ -20,6 +20,7 @@ struct bcm43xx_dfsentry {
20 struct dentry *dentry_spromdump; 20 struct dentry *dentry_spromdump;
21 struct dentry *dentry_tsf; 21 struct dentry *dentry_tsf;
22 struct dentry *dentry_txstat; 22 struct dentry *dentry_txstat;
23 struct dentry *dentry_restart;
23 24
24 struct bcm43xx_private *bcm; 25 struct bcm43xx_private *bcm;
25 26
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index ab3a0ee9fac8..b095f3cc6730 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -509,23 +509,19 @@ static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm)
509} 509}
510 510
511/* Make sure we don't receive more data from the device. */ 511/* Make sure we don't receive more data from the device. */
512static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate) 512static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm)
513{ 513{
514 unsigned long flags; 514 unsigned long flags;
515 u32 old;
516 515
517 spin_lock_irqsave(&bcm->irq_lock, flags); 516 spin_lock_irqsave(&bcm->irq_lock, flags);
518 if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { 517 if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
519 spin_unlock_irqrestore(&bcm->irq_lock, flags); 518 spin_unlock_irqrestore(&bcm->irq_lock, flags);
520 return -EBUSY; 519 return -EBUSY;
521 } 520 }
522 old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 521 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
523 spin_unlock_irqrestore(&bcm->irq_lock, flags); 522 spin_unlock_irqrestore(&bcm->irq_lock, flags);
524 bcm43xx_synchronize_irq(bcm); 523 bcm43xx_synchronize_irq(bcm);
525 524
526 if (oldstate)
527 *oldstate = old;
528
529 return 0; 525 return 0;
530} 526}
531 527
@@ -537,7 +533,6 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
537 u16 manufact; 533 u16 manufact;
538 u16 version; 534 u16 version;
539 u8 revision; 535 u8 revision;
540 s8 i;
541 536
542 if (bcm->chip_id == 0x4317) { 537 if (bcm->chip_id == 0x4317) {
543 if (bcm->chip_rev == 0x00) 538 if (bcm->chip_rev == 0x00)
@@ -580,20 +575,11 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
580 radio->version = version; 575 radio->version = version;
581 radio->revision = revision; 576 radio->revision = revision;
582 577
583 /* Set default attenuation values. */
584 radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
585 radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
586 radio->txctl1 = bcm43xx_default_txctl1(bcm);
587 radio->txctl2 = 0xFFFF;
588 if (phy->type == BCM43xx_PHYTYPE_A) 578 if (phy->type == BCM43xx_PHYTYPE_A)
589 radio->txpower_desired = bcm->sprom.maxpower_aphy; 579 radio->txpower_desired = bcm->sprom.maxpower_aphy;
590 else 580 else
591 radio->txpower_desired = bcm->sprom.maxpower_bgphy; 581 radio->txpower_desired = bcm->sprom.maxpower_bgphy;
592 582
593 /* Initialize the in-memory nrssi Lookup Table. */
594 for (i = 0; i < 64; i++)
595 radio->nrssi_lt[i] = i;
596
597 return 0; 583 return 0;
598 584
599err_unsupported_radio: 585err_unsupported_radio:
@@ -1250,10 +1236,6 @@ int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *ne
1250 goto out; 1236 goto out;
1251 1237
1252 bcm->current_core = new_core; 1238 bcm->current_core = new_core;
1253 bcm->current_80211_core_idx = -1;
1254 if (new_core->id == BCM43xx_COREID_80211)
1255 bcm->current_80211_core_idx = (int)(new_core - &(bcm->core_80211[0]));
1256
1257out: 1239out:
1258 return err; 1240 return err;
1259} 1241}
@@ -1423,43 +1405,23 @@ static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm)
1423 bcm43xx_core_disable(bcm, 0); 1405 bcm43xx_core_disable(bcm, 0);
1424} 1406}
1425 1407
1426/* Mark the current 80211 core inactive. 1408/* Mark the current 80211 core inactive. */
1427 * "active_80211_core" is the other 80211 core, which is used. 1409static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm)
1428 */
1429static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm,
1430 struct bcm43xx_coreinfo *active_80211_core)
1431{ 1410{
1432 u32 sbtmstatelow; 1411 u32 sbtmstatelow;
1433 struct bcm43xx_coreinfo *old_core;
1434 int err = 0;
1435 1412
1436 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 1413 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
1437 bcm43xx_radio_turn_off(bcm); 1414 bcm43xx_radio_turn_off(bcm);
1438 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); 1415 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1439 sbtmstatelow &= ~0x200a0000; 1416 sbtmstatelow &= 0xDFF5FFFF;
1440 sbtmstatelow |= 0xa0000; 1417 sbtmstatelow |= 0x000A0000;
1441 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); 1418 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1442 udelay(1); 1419 udelay(1);
1443 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); 1420 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1444 sbtmstatelow &= ~0xa0000; 1421 sbtmstatelow &= 0xFFF5FFFF;
1445 sbtmstatelow |= 0x80000; 1422 sbtmstatelow |= 0x00080000;
1446 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); 1423 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1447 udelay(1); 1424 udelay(1);
1448
1449 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G) {
1450 old_core = bcm->current_core;
1451 err = bcm43xx_switch_core(bcm, active_80211_core);
1452 if (err)
1453 goto out;
1454 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1455 sbtmstatelow &= ~0x20000000;
1456 sbtmstatelow |= 0x20000000;
1457 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1458 err = bcm43xx_switch_core(bcm, old_core);
1459 }
1460
1461out:
1462 return err;
1463} 1425}
1464 1426
1465static void handle_irq_transmit_status(struct bcm43xx_private *bcm) 1427static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
@@ -1885,14 +1847,8 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
1885 1847
1886 spin_lock(&bcm->irq_lock); 1848 spin_lock(&bcm->irq_lock);
1887 1849
1888 /* Only accept IRQs, if we are initialized properly. 1850 assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
1889 * This avoids an RX race while initializing. 1851 assert(bcm->current_core->id == BCM43xx_COREID_80211);
1890 * We should probably not enable IRQs before we are initialized
1891 * completely, but some careful work is needed to fix this. I think it
1892 * is best to stay with this cheap workaround for now... .
1893 */
1894 if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED))
1895 goto out;
1896 1852
1897 reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); 1853 reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
1898 if (reason == 0xffffffff) { 1854 if (reason == 0xffffffff) {
@@ -1930,16 +1886,18 @@ out:
1930 1886
1931static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) 1887static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
1932{ 1888{
1889 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1890
1933 if (bcm->firmware_norelease && !force) 1891 if (bcm->firmware_norelease && !force)
1934 return; /* Suspending or controller reset. */ 1892 return; /* Suspending or controller reset. */
1935 release_firmware(bcm->ucode); 1893 release_firmware(phy->ucode);
1936 bcm->ucode = NULL; 1894 phy->ucode = NULL;
1937 release_firmware(bcm->pcm); 1895 release_firmware(phy->pcm);
1938 bcm->pcm = NULL; 1896 phy->pcm = NULL;
1939 release_firmware(bcm->initvals0); 1897 release_firmware(phy->initvals0);
1940 bcm->initvals0 = NULL; 1898 phy->initvals0 = NULL;
1941 release_firmware(bcm->initvals1); 1899 release_firmware(phy->initvals1);
1942 bcm->initvals1 = NULL; 1900 phy->initvals1 = NULL;
1943} 1901}
1944 1902
1945static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) 1903static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
@@ -1950,11 +1908,11 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
1950 int nr; 1908 int nr;
1951 char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 }; 1909 char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
1952 1910
1953 if (!bcm->ucode) { 1911 if (!phy->ucode) {
1954 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw", 1912 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
1955 (rev >= 5 ? 5 : rev), 1913 (rev >= 5 ? 5 : rev),
1956 modparam_fwpostfix); 1914 modparam_fwpostfix);
1957 err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev); 1915 err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev);
1958 if (err) { 1916 if (err) {
1959 printk(KERN_ERR PFX 1917 printk(KERN_ERR PFX
1960 "Error: Microcode \"%s\" not available or load failed.\n", 1918 "Error: Microcode \"%s\" not available or load failed.\n",
@@ -1963,12 +1921,12 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
1963 } 1921 }
1964 } 1922 }
1965 1923
1966 if (!bcm->pcm) { 1924 if (!phy->pcm) {
1967 snprintf(buf, ARRAY_SIZE(buf), 1925 snprintf(buf, ARRAY_SIZE(buf),
1968 "bcm43xx_pcm%d%s.fw", 1926 "bcm43xx_pcm%d%s.fw",
1969 (rev < 5 ? 4 : 5), 1927 (rev < 5 ? 4 : 5),
1970 modparam_fwpostfix); 1928 modparam_fwpostfix);
1971 err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev); 1929 err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev);
1972 if (err) { 1930 if (err) {
1973 printk(KERN_ERR PFX 1931 printk(KERN_ERR PFX
1974 "Error: PCM \"%s\" not available or load failed.\n", 1932 "Error: PCM \"%s\" not available or load failed.\n",
@@ -1977,7 +1935,7 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
1977 } 1935 }
1978 } 1936 }
1979 1937
1980 if (!bcm->initvals0) { 1938 if (!phy->initvals0) {
1981 if (rev == 2 || rev == 4) { 1939 if (rev == 2 || rev == 4) {
1982 switch (phy->type) { 1940 switch (phy->type) {
1983 case BCM43xx_PHYTYPE_A: 1941 case BCM43xx_PHYTYPE_A:
@@ -2008,20 +1966,20 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
2008 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", 1966 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
2009 nr, modparam_fwpostfix); 1967 nr, modparam_fwpostfix);
2010 1968
2011 err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev); 1969 err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev);
2012 if (err) { 1970 if (err) {
2013 printk(KERN_ERR PFX 1971 printk(KERN_ERR PFX
2014 "Error: InitVals \"%s\" not available or load failed.\n", 1972 "Error: InitVals \"%s\" not available or load failed.\n",
2015 buf); 1973 buf);
2016 goto error; 1974 goto error;
2017 } 1975 }
2018 if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) { 1976 if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) {
2019 printk(KERN_ERR PFX "InitVals fileformat error.\n"); 1977 printk(KERN_ERR PFX "InitVals fileformat error.\n");
2020 goto error; 1978 goto error;
2021 } 1979 }
2022 } 1980 }
2023 1981
2024 if (!bcm->initvals1) { 1982 if (!phy->initvals1) {
2025 if (rev >= 5) { 1983 if (rev >= 5) {
2026 u32 sbtmstatehigh; 1984 u32 sbtmstatehigh;
2027 1985
@@ -2043,14 +2001,14 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
2043 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", 2001 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
2044 nr, modparam_fwpostfix); 2002 nr, modparam_fwpostfix);
2045 2003
2046 err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev); 2004 err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev);
2047 if (err) { 2005 if (err) {
2048 printk(KERN_ERR PFX 2006 printk(KERN_ERR PFX
2049 "Error: InitVals \"%s\" not available or load failed.\n", 2007 "Error: InitVals \"%s\" not available or load failed.\n",
2050 buf); 2008 buf);
2051 goto error; 2009 goto error;
2052 } 2010 }
2053 if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) { 2011 if (phy->initvals1->size % sizeof(struct bcm43xx_initval)) {
2054 printk(KERN_ERR PFX "InitVals fileformat error.\n"); 2012 printk(KERN_ERR PFX "InitVals fileformat error.\n");
2055 goto error; 2013 goto error;
2056 } 2014 }
@@ -2070,12 +2028,13 @@ err_noinitval:
2070 2028
2071static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) 2029static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
2072{ 2030{
2031 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2073 const u32 *data; 2032 const u32 *data;
2074 unsigned int i, len; 2033 unsigned int i, len;
2075 2034
2076 /* Upload Microcode. */ 2035 /* Upload Microcode. */
2077 data = (u32 *)(bcm->ucode->data); 2036 data = (u32 *)(phy->ucode->data);
2078 len = bcm->ucode->size / sizeof(u32); 2037 len = phy->ucode->size / sizeof(u32);
2079 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000); 2038 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
2080 for (i = 0; i < len; i++) { 2039 for (i = 0; i < len; i++) {
2081 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 2040 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
@@ -2084,8 +2043,8 @@ static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
2084 } 2043 }
2085 2044
2086 /* Upload PCM data. */ 2045 /* Upload PCM data. */
2087 data = (u32 *)(bcm->pcm->data); 2046 data = (u32 *)(phy->pcm->data);
2088 len = bcm->pcm->size / sizeof(u32); 2047 len = phy->pcm->size / sizeof(u32);
2089 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea); 2048 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
2090 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000); 2049 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
2091 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb); 2050 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
@@ -2131,15 +2090,16 @@ err_format:
2131 2090
2132static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) 2091static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
2133{ 2092{
2093 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2134 int err; 2094 int err;
2135 2095
2136 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, 2096 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data,
2137 bcm->initvals0->size / sizeof(struct bcm43xx_initval)); 2097 phy->initvals0->size / sizeof(struct bcm43xx_initval));
2138 if (err) 2098 if (err)
2139 goto out; 2099 goto out;
2140 if (bcm->initvals1) { 2100 if (phy->initvals1) {
2141 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data, 2101 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data,
2142 bcm->initvals1->size / sizeof(struct bcm43xx_initval)); 2102 phy->initvals1->size / sizeof(struct bcm43xx_initval));
2143 if (err) 2103 if (err)
2144 goto out; 2104 goto out;
2145 } 2105 }
@@ -2156,9 +2116,7 @@ static struct pci_device_id bcm43xx_47xx_ids[] = {
2156 2116
2157static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) 2117static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
2158{ 2118{
2159 int res; 2119 int err;
2160 unsigned int i;
2161 u32 data;
2162 2120
2163 bcm->irq = bcm->pci_dev->irq; 2121 bcm->irq = bcm->pci_dev->irq;
2164#ifdef CONFIG_BCM947XX 2122#ifdef CONFIG_BCM947XX
@@ -2175,32 +2133,12 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
2175 } 2133 }
2176 } 2134 }
2177#endif 2135#endif
2178 res = request_irq(bcm->irq, bcm43xx_interrupt_handler, 2136 err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
2179 IRQF_SHARED, KBUILD_MODNAME, bcm); 2137 IRQF_SHARED, KBUILD_MODNAME, bcm);
2180 if (res) { 2138 if (err)
2181 printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); 2139 printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
2182 return -ENODEV;
2183 }
2184 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff);
2185 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
2186 i = 0;
2187 while (1) {
2188 data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2189 if (data == BCM43xx_IRQ_READY)
2190 break;
2191 i++;
2192 if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
2193 printk(KERN_ERR PFX "Card IRQ register not responding. "
2194 "Giving up.\n");
2195 free_irq(bcm->irq, bcm);
2196 return -ENODEV;
2197 }
2198 udelay(10);
2199 }
2200 // dummy read
2201 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2202 2140
2203 return 0; 2141 return err;
2204} 2142}
2205 2143
2206/* Switch to the core used to write the GPIO register. 2144/* Switch to the core used to write the GPIO register.
@@ -2298,13 +2236,17 @@ static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
2298/* http://bcm-specs.sipsolutions.net/EnableMac */ 2236/* http://bcm-specs.sipsolutions.net/EnableMac */
2299void bcm43xx_mac_enable(struct bcm43xx_private *bcm) 2237void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
2300{ 2238{
2301 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 2239 bcm->mac_suspended--;
2302 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) 2240 assert(bcm->mac_suspended >= 0);
2303 | BCM43xx_SBF_MAC_ENABLED); 2241 if (bcm->mac_suspended == 0) {
2304 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY); 2242 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2305 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ 2243 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2306 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ 2244 | BCM43xx_SBF_MAC_ENABLED);
2307 bcm43xx_power_saving_ctl_bits(bcm, -1, -1); 2245 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
2246 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
2247 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2248 bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
2249 }
2308} 2250}
2309 2251
2310/* http://bcm-specs.sipsolutions.net/SuspendMAC */ 2252/* http://bcm-specs.sipsolutions.net/SuspendMAC */
@@ -2313,18 +2255,23 @@ void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
2313 int i; 2255 int i;
2314 u32 tmp; 2256 u32 tmp;
2315 2257
2316 bcm43xx_power_saving_ctl_bits(bcm, -1, 1); 2258 assert(bcm->mac_suspended >= 0);
2317 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 2259 if (bcm->mac_suspended == 0) {
2318 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) 2260 bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
2319 & ~BCM43xx_SBF_MAC_ENABLED); 2261 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2320 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ 2262 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2321 for (i = 100000; i; i--) { 2263 & ~BCM43xx_SBF_MAC_ENABLED);
2322 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); 2264 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2323 if (tmp & BCM43xx_IRQ_READY) 2265 for (i = 10000; i; i--) {
2324 return; 2266 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2325 udelay(10); 2267 if (tmp & BCM43xx_IRQ_READY)
2268 goto out;
2269 udelay(1);
2270 }
2271 printkl(KERN_ERR PFX "MAC suspend failed\n");
2326 } 2272 }
2327 printkl(KERN_ERR PFX "MAC suspend failed\n"); 2273out:
2274 bcm->mac_suspended++;
2328} 2275}
2329 2276
2330void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, 2277void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
@@ -2394,7 +2341,6 @@ static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
2394 if (!modparam_noleds) 2341 if (!modparam_noleds)
2395 bcm43xx_leds_exit(bcm); 2342 bcm43xx_leds_exit(bcm);
2396 bcm43xx_gpio_cleanup(bcm); 2343 bcm43xx_gpio_cleanup(bcm);
2397 free_irq(bcm->irq, bcm);
2398 bcm43xx_release_firmware(bcm, 0); 2344 bcm43xx_release_firmware(bcm, 0);
2399} 2345}
2400 2346
@@ -2406,7 +2352,7 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
2406 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); 2352 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2407 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 2353 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2408 int err; 2354 int err;
2409 int tmp; 2355 int i, tmp;
2410 u32 value32; 2356 u32 value32;
2411 u16 value16; 2357 u16 value16;
2412 2358
@@ -2419,13 +2365,26 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
2419 goto out; 2365 goto out;
2420 bcm43xx_upload_microcode(bcm); 2366 bcm43xx_upload_microcode(bcm);
2421 2367
2422 err = bcm43xx_initialize_irq(bcm); 2368 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF);
2423 if (err) 2369 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
2424 goto err_release_fw; 2370 i = 0;
2371 while (1) {
2372 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2373 if (value32 == BCM43xx_IRQ_READY)
2374 break;
2375 i++;
2376 if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
2377 printk(KERN_ERR PFX "IRQ_READY timeout\n");
2378 err = -ENODEV;
2379 goto err_release_fw;
2380 }
2381 udelay(10);
2382 }
2383 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2425 2384
2426 err = bcm43xx_gpio_init(bcm); 2385 err = bcm43xx_gpio_init(bcm);
2427 if (err) 2386 if (err)
2428 goto err_free_irq; 2387 goto err_release_fw;
2429 2388
2430 err = bcm43xx_upload_initvals(bcm); 2389 err = bcm43xx_upload_initvals(bcm);
2431 if (err) 2390 if (err)
@@ -2509,8 +2468,6 @@ err_radio_off:
2509 bcm43xx_radio_turn_off(bcm); 2468 bcm43xx_radio_turn_off(bcm);
2510err_gpio_cleanup: 2469err_gpio_cleanup:
2511 bcm43xx_gpio_cleanup(bcm); 2470 bcm43xx_gpio_cleanup(bcm);
2512err_free_irq:
2513 free_irq(bcm->irq, bcm);
2514err_release_fw: 2471err_release_fw:
2515 bcm43xx_release_firmware(bcm, 1); 2472 bcm43xx_release_firmware(bcm, 1);
2516 goto out; 2473 goto out;
@@ -2550,11 +2507,9 @@ static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy)
2550{ 2507{
2551 /* Initialize a "phyinfo" structure. The structure is already 2508 /* Initialize a "phyinfo" structure. The structure is already
2552 * zeroed out. 2509 * zeroed out.
2510 * This is called on insmod time to initialize members.
2553 */ 2511 */
2554 phy->antenna_diversity = 0xFFFF;
2555 phy->savedpctlreg = 0xFFFF; 2512 phy->savedpctlreg = 0xFFFF;
2556 phy->minlowsig[0] = 0xFFFF;
2557 phy->minlowsig[1] = 0xFFFF;
2558 spin_lock_init(&phy->lock); 2513 spin_lock_init(&phy->lock);
2559} 2514}
2560 2515
@@ -2562,14 +2517,11 @@ static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio)
2562{ 2517{
2563 /* Initialize a "radioinfo" structure. The structure is already 2518 /* Initialize a "radioinfo" structure. The structure is already
2564 * zeroed out. 2519 * zeroed out.
2520 * This is called on insmod time to initialize members.
2565 */ 2521 */
2566 radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; 2522 radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
2567 radio->channel = 0xFF; 2523 radio->channel = 0xFF;
2568 radio->initial_channel = 0xFF; 2524 radio->initial_channel = 0xFF;
2569 radio->lofcal = 0xFFFF;
2570 radio->initval = 0xFFFF;
2571 radio->nrssi[0] = -1000;
2572 radio->nrssi[1] = -1000;
2573} 2525}
2574 2526
2575static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) 2527static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
@@ -2587,7 +2539,6 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
2587 * BCM43xx_MAX_80211_CORES); 2539 * BCM43xx_MAX_80211_CORES);
2588 memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211) 2540 memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
2589 * BCM43xx_MAX_80211_CORES); 2541 * BCM43xx_MAX_80211_CORES);
2590 bcm->current_80211_core_idx = -1;
2591 bcm->nr_80211_available = 0; 2542 bcm->nr_80211_available = 0;
2592 bcm->current_core = NULL; 2543 bcm->current_core = NULL;
2593 bcm->active_80211_core = NULL; 2544 bcm->active_80211_core = NULL;
@@ -2757,6 +2708,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
2757 goto out; 2708 goto out;
2758 } 2709 }
2759 bcm->nr_80211_available++; 2710 bcm->nr_80211_available++;
2711 core->priv = ext_80211;
2760 bcm43xx_init_struct_phyinfo(&ext_80211->phy); 2712 bcm43xx_init_struct_phyinfo(&ext_80211->phy);
2761 bcm43xx_init_struct_radioinfo(&ext_80211->radio); 2713 bcm43xx_init_struct_radioinfo(&ext_80211->radio);
2762 break; 2714 break;
@@ -2857,7 +2809,8 @@ static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
2857} 2809}
2858 2810
2859/* http://bcm-specs.sipsolutions.net/80211Init */ 2811/* http://bcm-specs.sipsolutions.net/80211Init */
2860static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) 2812static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
2813 int active_wlcore)
2861{ 2814{
2862 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 2815 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2863 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); 2816 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
@@ -2939,19 +2892,26 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm)
2939 if (bcm->current_core->rev >= 5) 2892 if (bcm->current_core->rev >= 5)
2940 bcm43xx_write16(bcm, 0x043C, 0x000C); 2893 bcm43xx_write16(bcm, 0x043C, 0x000C);
2941 2894
2942 if (bcm43xx_using_pio(bcm)) 2895 if (active_wlcore) {
2943 err = bcm43xx_pio_init(bcm); 2896 if (bcm43xx_using_pio(bcm))
2944 else 2897 err = bcm43xx_pio_init(bcm);
2945 err = bcm43xx_dma_init(bcm); 2898 else
2946 if (err) 2899 err = bcm43xx_dma_init(bcm);
2947 goto err_chip_cleanup; 2900 if (err)
2901 goto err_chip_cleanup;
2902 }
2948 bcm43xx_write16(bcm, 0x0612, 0x0050); 2903 bcm43xx_write16(bcm, 0x0612, 0x0050);
2949 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); 2904 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
2950 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); 2905 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
2951 2906
2952 bcm43xx_mac_enable(bcm); 2907 if (active_wlcore) {
2953 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); 2908 if (radio->initial_channel != 0xFF)
2909 bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0);
2910 }
2954 2911
2912 /* Don't enable MAC/IRQ here, as it will race with the IRQ handler.
2913 * We enable it later.
2914 */
2955 bcm->current_core->initialized = 1; 2915 bcm->current_core->initialized = 1;
2956out: 2916out:
2957 return err; 2917 return err;
@@ -3066,11 +3026,6 @@ out:
3066 return err; 3026 return err;
3067} 3027}
3068 3028
3069static void bcm43xx_softmac_init(struct bcm43xx_private *bcm)
3070{
3071 ieee80211softmac_start(bcm->net_dev);
3072}
3073
3074static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) 3029static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
3075{ 3030{
3076 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 3031 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
@@ -3183,7 +3138,9 @@ static void bcm43xx_periodic_work_handler(void *d)
3183 * be preemtible. 3138 * be preemtible.
3184 */ 3139 */
3185 netif_stop_queue(bcm->net_dev); 3140 netif_stop_queue(bcm->net_dev);
3141 synchronize_net();
3186 spin_lock_irqsave(&bcm->irq_lock, flags); 3142 spin_lock_irqsave(&bcm->irq_lock, flags);
3143 bcm43xx_mac_suspend(bcm);
3187 if (bcm43xx_using_pio(bcm)) 3144 if (bcm43xx_using_pio(bcm))
3188 bcm43xx_pio_freeze_txqueues(bcm); 3145 bcm43xx_pio_freeze_txqueues(bcm);
3189 savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 3146 savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
@@ -3207,6 +3164,7 @@ static void bcm43xx_periodic_work_handler(void *d)
3207 bcm43xx_interrupt_enable(bcm, savedirqs); 3164 bcm43xx_interrupt_enable(bcm, savedirqs);
3208 if (bcm43xx_using_pio(bcm)) 3165 if (bcm43xx_using_pio(bcm))
3209 bcm43xx_pio_thaw_txqueues(bcm); 3166 bcm43xx_pio_thaw_txqueues(bcm);
3167 bcm43xx_mac_enable(bcm);
3210 } 3168 }
3211 netif_wake_queue(bcm->net_dev); 3169 netif_wake_queue(bcm->net_dev);
3212 } 3170 }
@@ -3241,9 +3199,9 @@ static int bcm43xx_rng_read(struct hwrng *rng, u32 *data)
3241 struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv; 3199 struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv;
3242 unsigned long flags; 3200 unsigned long flags;
3243 3201
3244 bcm43xx_lock_irqonly(bcm, flags); 3202 spin_lock_irqsave(&(bcm)->irq_lock, flags);
3245 *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG); 3203 *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG);
3246 bcm43xx_unlock_irqonly(bcm, flags); 3204 spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
3247 3205
3248 return (sizeof(u16)); 3206 return (sizeof(u16));
3249} 3207}
@@ -3269,139 +3227,322 @@ static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
3269 return err; 3227 return err;
3270} 3228}
3271 3229
3272/* This is the opposite of bcm43xx_init_board() */ 3230static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
3273static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3274{ 3231{
3232 int ret = 0;
3275 int i, err; 3233 int i, err;
3234 struct bcm43xx_coreinfo *core;
3276 3235
3277 mutex_lock(&bcm->mutex); 3236 bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
3237 for (i = 0; i < bcm->nr_80211_available; i++) {
3238 core = &(bcm->core_80211[i]);
3239 assert(core->available);
3240 if (!core->initialized)
3241 continue;
3242 err = bcm43xx_switch_core(bcm, core);
3243 if (err) {
3244 dprintk(KERN_ERR PFX "shutdown_all_wireless_cores "
3245 "switch_core failed (%d)\n", err);
3246 ret = err;
3247 continue;
3248 }
3249 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3250 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
3251 bcm43xx_wireless_core_cleanup(bcm);
3252 if (core == bcm->active_80211_core)
3253 bcm->active_80211_core = NULL;
3254 }
3255 free_irq(bcm->irq, bcm);
3256 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
3257
3258 return ret;
3259}
3260
3261/* This is the opposite of bcm43xx_init_board() */
3262static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3263{
3278 bcm43xx_sysfs_unregister(bcm); 3264 bcm43xx_sysfs_unregister(bcm);
3279 bcm43xx_periodic_tasks_delete(bcm); 3265 bcm43xx_periodic_tasks_delete(bcm);
3280 3266
3281 bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); 3267 mutex_lock(&(bcm)->mutex);
3268 bcm43xx_shutdown_all_wireless_cores(bcm);
3269 bcm43xx_pctl_set_crystal(bcm, 0);
3270 mutex_unlock(&(bcm)->mutex);
3271}
3272
3273static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy)
3274{
3275 phy->antenna_diversity = 0xFFFF;
3276 memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
3277 memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
3278
3279 /* Flags */
3280 phy->calibrated = 0;
3281 phy->is_locked = 0;
3282
3283 if (phy->_lo_pairs) {
3284 memset(phy->_lo_pairs, 0,
3285 sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT);
3286 }
3287 memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain));
3288}
3289
3290static void prepare_radiodata_for_init(struct bcm43xx_private *bcm,
3291 struct bcm43xx_radioinfo *radio)
3292{
3293 int i;
3294
3295 /* Set default attenuation values. */
3296 radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
3297 radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
3298 radio->txctl1 = bcm43xx_default_txctl1(bcm);
3299 radio->txctl2 = 0xFFFF;
3300 radio->txpwr_offset = 0;
3301
3302 /* NRSSI */
3303 radio->nrssislope = 0;
3304 for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++)
3305 radio->nrssi[i] = -1000;
3306 for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++)
3307 radio->nrssi_lt[i] = i;
3308
3309 radio->lofcal = 0xFFFF;
3310 radio->initval = 0xFFFF;
3311
3312 radio->aci_enable = 0;
3313 radio->aci_wlan_automatic = 0;
3314 radio->aci_hw_rssi = 0;
3315}
3316
3317static void prepare_priv_for_init(struct bcm43xx_private *bcm)
3318{
3319 int i;
3320 struct bcm43xx_coreinfo *core;
3321 struct bcm43xx_coreinfo_80211 *wlext;
3322
3323 assert(!bcm->active_80211_core);
3324
3325 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
3282 3326
3283 bcm43xx_rng_exit(bcm); 3327 /* Flags */
3328 bcm->was_initialized = 0;
3329 bcm->reg124_set_0x4 = 0;
3330
3331 /* Stats */
3332 memset(&bcm->stats, 0, sizeof(bcm->stats));
3333
3334 /* Wireless core data */
3284 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { 3335 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3285 if (!bcm->core_80211[i].available) 3336 core = &(bcm->core_80211[i]);
3286 continue; 3337 wlext = core->priv;
3287 if (!bcm->core_80211[i].initialized) 3338
3339 if (!core->available)
3288 continue; 3340 continue;
3341 assert(wlext == &(bcm->core_80211_ext[i]));
3289 3342
3290 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); 3343 prepare_phydata_for_init(&wlext->phy);
3291 assert(err == 0); 3344 prepare_radiodata_for_init(bcm, &wlext->radio);
3292 bcm43xx_wireless_core_cleanup(bcm);
3293 } 3345 }
3294 3346
3295 bcm43xx_pctl_set_crystal(bcm, 0); 3347 /* IRQ related flags */
3348 bcm->irq_reason = 0;
3349 memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason));
3350 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
3296 3351
3297 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); 3352 /* Noise calculation context */
3298 mutex_unlock(&bcm->mutex); 3353 memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc));
3354
3355 /* Periodic work context */
3356 bcm->periodic_state = 0;
3299} 3357}
3300 3358
3301static int bcm43xx_init_board(struct bcm43xx_private *bcm) 3359static int wireless_core_up(struct bcm43xx_private *bcm,
3360 int active_wlcore)
3361{
3362 int err;
3363
3364 if (!bcm43xx_core_enabled(bcm))
3365 bcm43xx_wireless_core_reset(bcm, 1);
3366 if (!active_wlcore)
3367 bcm43xx_wireless_core_mark_inactive(bcm);
3368 err = bcm43xx_wireless_core_init(bcm, active_wlcore);
3369 if (err)
3370 goto out;
3371 if (!active_wlcore)
3372 bcm43xx_radio_turn_off(bcm);
3373out:
3374 return err;
3375}
3376
3377/* Select and enable the "to be used" wireless core.
3378 * Locking: bcm->mutex must be aquired before calling this.
3379 * bcm->irq_lock must not be aquired.
3380 */
3381int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
3382 int phytype)
3302{ 3383{
3303 int i, err; 3384 int i, err;
3304 int connect_phy; 3385 struct bcm43xx_coreinfo *active_core = NULL;
3386 struct bcm43xx_coreinfo_80211 *active_wlext = NULL;
3387 struct bcm43xx_coreinfo *core;
3388 struct bcm43xx_coreinfo_80211 *wlext;
3389 int adjust_active_sbtmstatelow = 0;
3305 3390
3306 might_sleep(); 3391 might_sleep();
3307 3392
3308 mutex_lock(&bcm->mutex); 3393 if (phytype < 0) {
3309 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); 3394 /* If no phytype is requested, select the first core. */
3395 assert(bcm->core_80211[0].available);
3396 wlext = bcm->core_80211[0].priv;
3397 phytype = wlext->phy.type;
3398 }
3399 /* Find the requested core. */
3400 for (i = 0; i < bcm->nr_80211_available; i++) {
3401 core = &(bcm->core_80211[i]);
3402 wlext = core->priv;
3403 if (wlext->phy.type == phytype) {
3404 active_core = core;
3405 active_wlext = wlext;
3406 break;
3407 }
3408 }
3409 if (!active_core)
3410 return -ESRCH; /* No such PHYTYPE on this board. */
3411
3412 if (bcm->active_80211_core) {
3413 /* We already selected a wl core in the past.
3414 * So first clean up everything.
3415 */
3416 dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n");
3417 ieee80211softmac_stop(bcm->net_dev);
3418 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
3419 err = bcm43xx_disable_interrupts_sync(bcm);
3420 assert(!err);
3421 tasklet_enable(&bcm->isr_tasklet);
3422 err = bcm43xx_shutdown_all_wireless_cores(bcm);
3423 if (err)
3424 goto error;
3425 /* Ok, everything down, continue to re-initialize. */
3426 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
3427 }
3428
3429 /* Reset all data structures. */
3430 prepare_priv_for_init(bcm);
3310 3431
3311 err = bcm43xx_pctl_set_crystal(bcm, 1);
3312 if (err)
3313 goto out;
3314 err = bcm43xx_pctl_init(bcm);
3315 if (err)
3316 goto err_crystal_off;
3317 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST); 3432 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
3318 if (err) 3433 if (err)
3319 goto err_crystal_off; 3434 goto error;
3320 3435
3321 tasklet_enable(&bcm->isr_tasklet); 3436 /* Mark all unused cores "inactive". */
3322 for (i = 0; i < bcm->nr_80211_available; i++) { 3437 for (i = 0; i < bcm->nr_80211_available; i++) {
3323 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); 3438 core = &(bcm->core_80211[i]);
3324 assert(err != -ENODEV); 3439 wlext = core->priv;
3325 if (err)
3326 goto err_80211_unwind;
3327 3440
3328 /* Enable the selected wireless core. 3441 if (core == active_core)
3329 * Connect PHY only on the first core. 3442 continue;
3330 */ 3443 err = bcm43xx_switch_core(bcm, core);
3331 if (!bcm43xx_core_enabled(bcm)) { 3444 if (err) {
3332 if (bcm->nr_80211_available == 1) { 3445 dprintk(KERN_ERR PFX "Could not switch to inactive "
3333 connect_phy = bcm43xx_current_phy(bcm)->connected; 3446 "802.11 core (%d)\n", err);
3334 } else { 3447 goto error;
3335 if (i == 0)
3336 connect_phy = 1;
3337 else
3338 connect_phy = 0;
3339 }
3340 bcm43xx_wireless_core_reset(bcm, connect_phy);
3341 } 3448 }
3449 err = wireless_core_up(bcm, 0);
3450 if (err) {
3451 dprintk(KERN_ERR PFX "core_up for inactive 802.11 core "
3452 "failed (%d)\n", err);
3453 goto error;
3454 }
3455 adjust_active_sbtmstatelow = 1;
3456 }
3342 3457
3343 if (i != 0) 3458 /* Now initialize the active 802.11 core. */
3344 bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]); 3459 err = bcm43xx_switch_core(bcm, active_core);
3345 3460 if (err) {
3346 err = bcm43xx_wireless_core_init(bcm); 3461 dprintk(KERN_ERR PFX "Could not switch to active "
3347 if (err) 3462 "802.11 core (%d)\n", err);
3348 goto err_80211_unwind; 3463 goto error;
3464 }
3465 if (adjust_active_sbtmstatelow &&
3466 active_wlext->phy.type == BCM43xx_PHYTYPE_G) {
3467 u32 sbtmstatelow;
3349 3468
3350 if (i != 0) { 3469 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
3351 bcm43xx_mac_suspend(bcm); 3470 sbtmstatelow |= 0x20000000;
3352 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 3471 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
3353 bcm43xx_radio_turn_off(bcm);
3354 }
3355 } 3472 }
3356 bcm->active_80211_core = &bcm->core_80211[0]; 3473 err = wireless_core_up(bcm, 1);
3357 if (bcm->nr_80211_available >= 2) { 3474 if (err) {
3358 bcm43xx_switch_core(bcm, &bcm->core_80211[0]); 3475 dprintk(KERN_ERR PFX "core_up for active 802.11 core "
3359 bcm43xx_mac_enable(bcm); 3476 "failed (%d)\n", err);
3477 goto error;
3360 } 3478 }
3361 err = bcm43xx_rng_init(bcm); 3479 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
3362 if (err) 3480 if (err)
3363 goto err_80211_unwind; 3481 goto error;
3482 bcm->active_80211_core = active_core;
3483
3364 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); 3484 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
3365 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); 3485 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
3366 dprintk(KERN_INFO PFX "80211 cores initialized\n");
3367 bcm43xx_security_init(bcm); 3486 bcm43xx_security_init(bcm);
3368 bcm43xx_softmac_init(bcm); 3487 ieee80211softmac_start(bcm->net_dev);
3369 3488
3370 bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); 3489 /* Let's go! Be careful after enabling the IRQs.
3490 * Don't switch cores, for example.
3491 */
3492 bcm43xx_mac_enable(bcm);
3493 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
3494 err = bcm43xx_initialize_irq(bcm);
3495 if (err)
3496 goto error;
3497 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
3371 3498
3372 if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) { 3499 dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n",
3373 bcm43xx_mac_suspend(bcm); 3500 active_wlext->phy.type);
3374 bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0);
3375 bcm43xx_mac_enable(bcm);
3376 }
3377 3501
3378 /* Initialization of the board is done. Flag it as such. */ 3502 return 0;
3379 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); 3503
3504error:
3505 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
3506 bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
3507 return err;
3508}
3509
3510static int bcm43xx_init_board(struct bcm43xx_private *bcm)
3511{
3512 int err;
3513
3514 mutex_lock(&(bcm)->mutex);
3515
3516 tasklet_enable(&bcm->isr_tasklet);
3517 err = bcm43xx_pctl_set_crystal(bcm, 1);
3518 if (err)
3519 goto err_tasklet;
3520 err = bcm43xx_pctl_init(bcm);
3521 if (err)
3522 goto err_crystal_off;
3523 err = bcm43xx_select_wireless_core(bcm, -1);
3524 if (err)
3525 goto err_crystal_off;
3380 3526
3381 bcm43xx_periodic_tasks_setup(bcm); 3527 bcm43xx_periodic_tasks_setup(bcm);
3382 bcm43xx_sysfs_register(bcm); 3528 err = bcm43xx_sysfs_register(bcm);
3383 //FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though... 3529 if (err)
3530 goto err_wlshutdown;
3384 3531
3385 /*FIXME: This should be handled by softmac instead. */ 3532 /*FIXME: This should be handled by softmac instead. */
3386 schedule_work(&bcm->softmac->associnfo.work); 3533 schedule_work(&bcm->softmac->associnfo.work);
3387 3534
3388 assert(err == 0);
3389out: 3535out:
3390 mutex_unlock(&bcm->mutex); 3536 mutex_unlock(&(bcm)->mutex);
3391 3537
3392 return err; 3538 return err;
3393 3539
3394err_80211_unwind: 3540err_wlshutdown:
3395 tasklet_disable(&bcm->isr_tasklet); 3541 bcm43xx_shutdown_all_wireless_cores(bcm);
3396 /* unwind all 80211 initialization */
3397 for (i = 0; i < bcm->nr_80211_available; i++) {
3398 if (!bcm->core_80211[i].initialized)
3399 continue;
3400 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3401 bcm43xx_wireless_core_cleanup(bcm);
3402 }
3403err_crystal_off: 3542err_crystal_off:
3404 bcm43xx_pctl_set_crystal(bcm, 0); 3543 bcm43xx_pctl_set_crystal(bcm, 0);
3544err_tasklet:
3545 tasklet_disable(&bcm->isr_tasklet);
3405 goto out; 3546 goto out;
3406} 3547}
3407 3548
@@ -3783,7 +3924,8 @@ static void bcm43xx_net_poll_controller(struct net_device *net_dev)
3783 unsigned long flags; 3924 unsigned long flags;
3784 3925
3785 local_irq_save(flags); 3926 local_irq_save(flags);
3786 bcm43xx_interrupt_handler(bcm->irq, bcm, NULL); 3927 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
3928 bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
3787 local_irq_restore(flags); 3929 local_irq_restore(flags);
3788} 3930}
3789#endif /* CONFIG_NET_POLL_CONTROLLER */ 3931#endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -3801,7 +3943,7 @@ static int bcm43xx_net_stop(struct net_device *net_dev)
3801 int err; 3943 int err;
3802 3944
3803 ieee80211softmac_stop(net_dev); 3945 ieee80211softmac_stop(net_dev);
3804 err = bcm43xx_disable_interrupts_sync(bcm, NULL); 3946 err = bcm43xx_disable_interrupts_sync(bcm);
3805 assert(!err); 3947 assert(!err);
3806 bcm43xx_free_board(bcm); 3948 bcm43xx_free_board(bcm);
3807 3949
@@ -3820,6 +3962,7 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
3820 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; 3962 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
3821 3963
3822 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; 3964 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
3965 bcm->mac_suspended = 1;
3823 bcm->pci_dev = pci_dev; 3966 bcm->pci_dev = pci_dev;
3824 bcm->net_dev = net_dev; 3967 bcm->net_dev = net_dev;
3825 bcm->bad_frames_preempt = modparam_bad_frames_preempt; 3968 bcm->bad_frames_preempt = modparam_bad_frames_preempt;
@@ -3943,7 +4086,6 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
3943 bcm43xx_debugfs_remove_device(bcm); 4086 bcm43xx_debugfs_remove_device(bcm);
3944 unregister_netdev(net_dev); 4087 unregister_netdev(net_dev);
3945 bcm43xx_detach_board(bcm); 4088 bcm43xx_detach_board(bcm);
3946 assert(bcm->ucode == NULL);
3947 free_ieee80211softmac(net_dev); 4089 free_ieee80211softmac(net_dev);
3948} 4090}
3949 4091
@@ -3953,47 +4095,25 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
3953static void bcm43xx_chip_reset(void *_bcm) 4095static void bcm43xx_chip_reset(void *_bcm)
3954{ 4096{
3955 struct bcm43xx_private *bcm = _bcm; 4097 struct bcm43xx_private *bcm = _bcm;
3956 struct net_device *net_dev = bcm->net_dev; 4098 struct bcm43xx_phyinfo *phy;
3957 struct pci_dev *pci_dev = bcm->pci_dev;
3958 int err; 4099 int err;
3959 int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
3960 4100
3961 netif_stop_queue(bcm->net_dev); 4101 mutex_lock(&(bcm)->mutex);
3962 tasklet_disable(&bcm->isr_tasklet); 4102 phy = bcm43xx_current_phy(bcm);
4103 err = bcm43xx_select_wireless_core(bcm, phy->type);
4104 mutex_unlock(&(bcm)->mutex);
3963 4105
3964 bcm->firmware_norelease = 1; 4106 printk(KERN_ERR PFX "Controller restart%s\n",
3965 if (was_initialized) 4107 (err == 0) ? "ed" : " failed");
3966 bcm43xx_free_board(bcm);
3967 bcm->firmware_norelease = 0;
3968 bcm43xx_detach_board(bcm);
3969 err = bcm43xx_init_private(bcm, net_dev, pci_dev);
3970 if (err)
3971 goto failure;
3972 err = bcm43xx_attach_board(bcm);
3973 if (err)
3974 goto failure;
3975 if (was_initialized) {
3976 err = bcm43xx_init_board(bcm);
3977 if (err)
3978 goto failure;
3979 }
3980 netif_wake_queue(bcm->net_dev);
3981 printk(KERN_INFO PFX "Controller restarted\n");
3982
3983 return;
3984failure:
3985 printk(KERN_ERR PFX "Controller restart failed\n");
3986} 4108}
3987 4109
3988/* Hard-reset the chip. 4110/* Hard-reset the chip.
3989 * This can be called from interrupt or process context. 4111 * This can be called from interrupt or process context.
3990 * Make sure to _not_ re-enable device interrupts after this has been called. 4112 */
3991*/
3992void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) 4113void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
3993{ 4114{
4115 assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
3994 bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING); 4116 bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING);
3995 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3996 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
3997 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); 4117 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
3998 INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); 4118 INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
3999 schedule_work(&bcm->restart_work); 4119 schedule_work(&bcm->restart_work);
@@ -4005,18 +4125,16 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
4005{ 4125{
4006 struct net_device *net_dev = pci_get_drvdata(pdev); 4126 struct net_device *net_dev = pci_get_drvdata(pdev);
4007 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 4127 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4008 int try_to_shutdown = 0, err; 4128 int err;
4009 4129
4010 dprintk(KERN_INFO PFX "Suspending...\n"); 4130 dprintk(KERN_INFO PFX "Suspending...\n");
4011 4131
4012 bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
4013 if (bcm->was_initialized)
4014 try_to_shutdown = 1;
4015
4016 netif_device_detach(net_dev); 4132 netif_device_detach(net_dev);
4017 if (try_to_shutdown) { 4133 bcm->was_initialized = 0;
4134 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
4135 bcm->was_initialized = 1;
4018 ieee80211softmac_stop(net_dev); 4136 ieee80211softmac_stop(net_dev);
4019 err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate); 4137 err = bcm43xx_disable_interrupts_sync(bcm);
4020 if (unlikely(err)) { 4138 if (unlikely(err)) {
4021 dprintk(KERN_ERR PFX "Suspend failed.\n"); 4139 dprintk(KERN_ERR PFX "Suspend failed.\n");
4022 return -EAGAIN; 4140 return -EAGAIN;
@@ -4049,17 +4167,14 @@ static int bcm43xx_resume(struct pci_dev *pdev)
4049 pci_restore_state(pdev); 4167 pci_restore_state(pdev);
4050 4168
4051 bcm43xx_chipset_attach(bcm); 4169 bcm43xx_chipset_attach(bcm);
4052 if (bcm->was_initialized) { 4170 if (bcm->was_initialized)
4053 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
4054 err = bcm43xx_init_board(bcm); 4171 err = bcm43xx_init_board(bcm);
4055 }
4056 if (err) { 4172 if (err) {
4057 printk(KERN_ERR PFX "Resume failed!\n"); 4173 printk(KERN_ERR PFX "Resume failed!\n");
4058 return err; 4174 return err;
4059 } 4175 }
4060
4061 netif_device_attach(net_dev); 4176 netif_device_attach(net_dev);
4062 4177
4063 dprintk(KERN_INFO PFX "Device resumed.\n"); 4178 dprintk(KERN_INFO PFX "Device resumed.\n");
4064 4179
4065 return 0; 4180 return 0;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
index 116493671f88..505c86e2007a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
@@ -133,6 +133,9 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
133 133
134int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core); 134int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
135 135
136int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
137 int phytype);
138
136void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); 139void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
137 140
138void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); 141void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
index cc1ff3c6f140..ece335178f6a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -309,6 +309,70 @@ static DEVICE_ATTR(shortpreamble, 0644,
309 bcm43xx_attr_preamble_show, 309 bcm43xx_attr_preamble_show,
310 bcm43xx_attr_preamble_store); 310 bcm43xx_attr_preamble_store);
311 311
312static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
313 struct device_attribute *attr,
314 const char *buf, size_t count)
315{
316 struct bcm43xx_private *bcm = dev_to_bcm(dev);
317 int phytype;
318 int err = -EINVAL;
319
320 if (count < 1)
321 goto out;
322 switch (buf[0]) {
323 case 'a': case 'A':
324 phytype = BCM43xx_PHYTYPE_A;
325 break;
326 case 'b': case 'B':
327 phytype = BCM43xx_PHYTYPE_B;
328 break;
329 case 'g': case 'G':
330 phytype = BCM43xx_PHYTYPE_G;
331 break;
332 default:
333 goto out;
334 }
335
336 mutex_lock(&(bcm)->mutex);
337 err = bcm43xx_select_wireless_core(bcm, phytype);
338 mutex_unlock(&(bcm)->mutex);
339 if (err == -ESRCH)
340 err = -ENODEV;
341
342out:
343 return err ? err : count;
344}
345
346static ssize_t bcm43xx_attr_phymode_show(struct device *dev,
347 struct device_attribute *attr,
348 char *buf)
349{
350 struct bcm43xx_private *bcm = dev_to_bcm(dev);
351 ssize_t count = 0;
352
353 mutex_lock(&(bcm)->mutex);
354 switch (bcm43xx_current_phy(bcm)->type) {
355 case BCM43xx_PHYTYPE_A:
356 snprintf(buf, PAGE_SIZE, "A");
357 break;
358 case BCM43xx_PHYTYPE_B:
359 snprintf(buf, PAGE_SIZE, "B");
360 break;
361 case BCM43xx_PHYTYPE_G:
362 snprintf(buf, PAGE_SIZE, "G");
363 break;
364 default:
365 assert(0);
366 }
367 mutex_unlock(&(bcm)->mutex);
368
369 return count;
370}
371
372static DEVICE_ATTR(phymode, 0644,
373 bcm43xx_attr_phymode_show,
374 bcm43xx_attr_phymode_store);
375
312int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) 376int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
313{ 377{
314 struct device *dev = &bcm->pci_dev->dev; 378 struct device *dev = &bcm->pci_dev->dev;
@@ -325,9 +389,14 @@ int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
325 err = device_create_file(dev, &dev_attr_shortpreamble); 389 err = device_create_file(dev, &dev_attr_shortpreamble);
326 if (err) 390 if (err)
327 goto err_remove_interfmode; 391 goto err_remove_interfmode;
392 err = device_create_file(dev, &dev_attr_phymode);
393 if (err)
394 goto err_remove_shortpreamble;
328 395
329out: 396out:
330 return err; 397 return err;
398err_remove_shortpreamble:
399 device_remove_file(dev, &dev_attr_shortpreamble);
331err_remove_interfmode: 400err_remove_interfmode:
332 device_remove_file(dev, &dev_attr_interference); 401 device_remove_file(dev, &dev_attr_interference);
333err_remove_sprom: 402err_remove_sprom:
@@ -339,6 +408,7 @@ void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
339{ 408{
340 struct device *dev = &bcm->pci_dev->dev; 409 struct device *dev = &bcm->pci_dev->dev;
341 410
411 device_remove_file(dev, &dev_attr_phymode);
342 device_remove_file(dev, &dev_attr_shortpreamble); 412 device_remove_file(dev, &dev_attr_shortpreamble);
343 device_remove_file(dev, &dev_attr_interference); 413 device_remove_file(dev, &dev_attr_interference);
344 device_remove_file(dev, &dev_attr_sprom); 414 device_remove_file(dev, &dev_attr_sprom);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index 8ffd760dc830..1d3a3aaf96ec 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -47,9 +47,8 @@
47#define BCM43xx_WX_VERSION 18 47#define BCM43xx_WX_VERSION 18
48 48
49#define MAX_WX_STRING 80 49#define MAX_WX_STRING 80
50/* FIXME: the next line is a guess as to what the maximum value of RX power 50/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
51 (in dBm) might be */ 51#define RX_RSSI_MAX 60
52#define RX_POWER_MAX -10
53 52
54 53
55static int bcm43xx_wx_get_name(struct net_device *net_dev, 54static int bcm43xx_wx_get_name(struct net_device *net_dev,
@@ -230,9 +229,8 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
230 range->throughput = 27 * 1000 * 1000; 229 range->throughput = 27 * 1000 * 1000;
231 230
232 range->max_qual.qual = 100; 231 range->max_qual.qual = 100;
233 /* TODO: Real max RSSI */ 232 range->max_qual.level = 152; /* set floor at -104 dBm (152 - 256) */
234 range->max_qual.level = 0; 233 range->max_qual.noise = 152;
235 range->max_qual.noise = 0;
236 range->max_qual.updated = IW_QUAL_ALL_UPDATED; 234 range->max_qual.updated = IW_QUAL_ALL_UPDATED;
237 235
238 range->avg_qual.qual = 50; 236 range->avg_qual.qual = 50;
@@ -845,6 +843,7 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d
845 struct iw_statistics *wstats; 843 struct iw_statistics *wstats;
846 struct ieee80211_network *network = NULL; 844 struct ieee80211_network *network = NULL;
847 static int tmp_level = 0; 845 static int tmp_level = 0;
846 static int tmp_qual = 0;
848 unsigned long flags; 847 unsigned long flags;
849 848
850 wstats = &bcm->stats.wstats; 849 wstats = &bcm->stats.wstats;
@@ -863,25 +862,28 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d
863 wstats->qual.level = 0; 862 wstats->qual.level = 0;
864 wstats->qual.noise = 0; 863 wstats->qual.noise = 0;
865 wstats->qual.updated = 7; 864 wstats->qual.updated = 7;
866 wstats->qual.updated |= IW_QUAL_ALL_UPDATED; 865 wstats->qual.updated |= IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
867 return wstats; 866 return wstats;
868 } 867 }
869 /* fill in the real statistics when iface associated */ 868 /* fill in the real statistics when iface associated */
870 spin_lock_irqsave(&mac->ieee->lock, flags); 869 spin_lock_irqsave(&mac->ieee->lock, flags);
871 list_for_each_entry(network, &mac->ieee->network_list, list) { 870 list_for_each_entry(network, &mac->ieee->network_list, list) {
872 if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) { 871 if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) {
873 if (!tmp_level) /* get initial value */ 872 if (!tmp_level) { /* get initial values */
874 tmp_level = network->stats.rssi; 873 tmp_level = network->stats.signal;
875 else /* smooth results */ 874 tmp_qual = network->stats.rssi;
876 tmp_level = (7 * tmp_level + network->stats.rssi)/8; 875 } else { /* smooth results */
876 tmp_level = (15 * tmp_level + network->stats.signal)/16;
877 tmp_qual = (15 * tmp_qual + network->stats.rssi)/16;
878 }
877 break; 879 break;
878 } 880 }
879 } 881 }
880 spin_unlock_irqrestore(&mac->ieee->lock, flags); 882 spin_unlock_irqrestore(&mac->ieee->lock, flags);
881 wstats->qual.level = tmp_level; 883 wstats->qual.level = tmp_level;
882 wstats->qual.qual = 100 + tmp_level - RX_POWER_MAX; // TODO: get the real signal quality 884 wstats->qual.qual = 100 * tmp_qual / RX_RSSI_MAX;
883 wstats->qual.noise = bcm->stats.noise; 885 wstats->qual.noise = bcm->stats.noise;
884 wstats->qual.updated = IW_QUAL_ALL_UPDATED; 886 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
885 wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable; 887 wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
886 wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded; 888 wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
887 wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa; 889 wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
index 6dbd855b3647..c0efbfe605a5 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -492,16 +492,15 @@ int bcm43xx_rx(struct bcm43xx_private *bcm,
492 492
493 memset(&stats, 0, sizeof(stats)); 493 memset(&stats, 0, sizeof(stats));
494 stats.mac_time = le16_to_cpu(rxhdr->mactime); 494 stats.mac_time = le16_to_cpu(rxhdr->mactime);
495 stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, 495 stats.rssi = rxhdr->rssi;
496 stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
496 !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), 497 !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
497 !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); 498 !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
498 stats.signal = rxhdr->signal_quality; //FIXME
499//TODO stats.noise = 499//TODO stats.noise =
500 if (is_ofdm) 500 if (is_ofdm)
501 stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp); 501 stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
502 else 502 else
503 stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp); 503 stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
504//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
505 stats.received_channel = radio->channel; 504 stats.received_channel = radio->channel;
506//TODO stats.control = 505//TODO stats.control =
507 stats.mask = IEEE80211_STATMASK_SIGNAL | 506 stats.mask = IEEE80211_STATMASK_SIGNAL |