aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/bcm43xx/bcm43xx_main.c
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2006-07-08 16:02:18 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-07-27 18:19:18 -0400
commit58e5528ee464d38040b9489e10033c9387a10d56 (patch)
tree58023ac8bf79757e37a4d05ce7fa63fb3f2388b9 /drivers/net/wireless/bcm43xx/bcm43xx_main.c
parent3234faa8abe0c3d6da12cc4a38ce790134c92564 (diff)
[PATCH] bcm43xx: init routine rewrite
Rewrite of the bcm43xx initialization routines. This fixes several issues: * up-down-up-down-up... stale data issue (May fix some DHCP issues) * Fix the init vs IRQ handler race (and remove the workaround) * Fix init for cards with multiple cores (APHY) As softmac has no internal PHY handling (unlike dscape), this adds the file "phymode" to sysfs. The active PHY can be selected by writing either a, b or g to this file. Current PHY can be determined by reading from it. * Fix the controller restart code. Controller restart can now also be triggered through echo 1 > /debug/bcm43xx/ethX/restart Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/bcm43xx/bcm43xx_main.c')
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c634
1 files changed, 367 insertions, 267 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 1c04722edaa0..e5829056cc3f 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.
@@ -2403,7 +2341,6 @@ static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
2403 if (!modparam_noleds) 2341 if (!modparam_noleds)
2404 bcm43xx_leds_exit(bcm); 2342 bcm43xx_leds_exit(bcm);
2405 bcm43xx_gpio_cleanup(bcm); 2343 bcm43xx_gpio_cleanup(bcm);
2406 free_irq(bcm->irq, bcm);
2407 bcm43xx_release_firmware(bcm, 0); 2344 bcm43xx_release_firmware(bcm, 0);
2408} 2345}
2409 2346
@@ -2415,7 +2352,7 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
2415 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); 2352 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2416 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 2353 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2417 int err; 2354 int err;
2418 int tmp; 2355 int i, tmp;
2419 u32 value32; 2356 u32 value32;
2420 u16 value16; 2357 u16 value16;
2421 2358
@@ -2428,13 +2365,26 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
2428 goto out; 2365 goto out;
2429 bcm43xx_upload_microcode(bcm); 2366 bcm43xx_upload_microcode(bcm);
2430 2367
2431 err = bcm43xx_initialize_irq(bcm); 2368 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF);
2432 if (err) 2369 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
2433 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 */
2434 2384
2435 err = bcm43xx_gpio_init(bcm); 2385 err = bcm43xx_gpio_init(bcm);
2436 if (err) 2386 if (err)
2437 goto err_free_irq; 2387 goto err_release_fw;
2438 2388
2439 err = bcm43xx_upload_initvals(bcm); 2389 err = bcm43xx_upload_initvals(bcm);
2440 if (err) 2390 if (err)
@@ -2518,8 +2468,6 @@ err_radio_off:
2518 bcm43xx_radio_turn_off(bcm); 2468 bcm43xx_radio_turn_off(bcm);
2519err_gpio_cleanup: 2469err_gpio_cleanup:
2520 bcm43xx_gpio_cleanup(bcm); 2470 bcm43xx_gpio_cleanup(bcm);
2521err_free_irq:
2522 free_irq(bcm->irq, bcm);
2523err_release_fw: 2471err_release_fw:
2524 bcm43xx_release_firmware(bcm, 1); 2472 bcm43xx_release_firmware(bcm, 1);
2525 goto out; 2473 goto out;
@@ -2559,11 +2507,9 @@ static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy)
2559{ 2507{
2560 /* Initialize a "phyinfo" structure. The structure is already 2508 /* Initialize a "phyinfo" structure. The structure is already
2561 * zeroed out. 2509 * zeroed out.
2510 * This is called on insmod time to initialize members.
2562 */ 2511 */
2563 phy->antenna_diversity = 0xFFFF;
2564 phy->savedpctlreg = 0xFFFF; 2512 phy->savedpctlreg = 0xFFFF;
2565 phy->minlowsig[0] = 0xFFFF;
2566 phy->minlowsig[1] = 0xFFFF;
2567 spin_lock_init(&phy->lock); 2513 spin_lock_init(&phy->lock);
2568} 2514}
2569 2515
@@ -2571,14 +2517,11 @@ static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio)
2571{ 2517{
2572 /* Initialize a "radioinfo" structure. The structure is already 2518 /* Initialize a "radioinfo" structure. The structure is already
2573 * zeroed out. 2519 * zeroed out.
2520 * This is called on insmod time to initialize members.
2574 */ 2521 */
2575 radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; 2522 radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
2576 radio->channel = 0xFF; 2523 radio->channel = 0xFF;
2577 radio->initial_channel = 0xFF; 2524 radio->initial_channel = 0xFF;
2578 radio->lofcal = 0xFFFF;
2579 radio->initval = 0xFFFF;
2580 radio->nrssi[0] = -1000;
2581 radio->nrssi[1] = -1000;
2582} 2525}
2583 2526
2584static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) 2527static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
@@ -2596,7 +2539,6 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
2596 * BCM43xx_MAX_80211_CORES); 2539 * BCM43xx_MAX_80211_CORES);
2597 memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211) 2540 memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
2598 * BCM43xx_MAX_80211_CORES); 2541 * BCM43xx_MAX_80211_CORES);
2599 bcm->current_80211_core_idx = -1;
2600 bcm->nr_80211_available = 0; 2542 bcm->nr_80211_available = 0;
2601 bcm->current_core = NULL; 2543 bcm->current_core = NULL;
2602 bcm->active_80211_core = NULL; 2544 bcm->active_80211_core = NULL;
@@ -2766,6 +2708,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
2766 goto out; 2708 goto out;
2767 } 2709 }
2768 bcm->nr_80211_available++; 2710 bcm->nr_80211_available++;
2711 core->priv = ext_80211;
2769 bcm43xx_init_struct_phyinfo(&ext_80211->phy); 2712 bcm43xx_init_struct_phyinfo(&ext_80211->phy);
2770 bcm43xx_init_struct_radioinfo(&ext_80211->radio); 2713 bcm43xx_init_struct_radioinfo(&ext_80211->radio);
2771 break; 2714 break;
@@ -2866,7 +2809,8 @@ static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
2866} 2809}
2867 2810
2868/* http://bcm-specs.sipsolutions.net/80211Init */ 2811/* http://bcm-specs.sipsolutions.net/80211Init */
2869static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) 2812static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
2813 int active_wlcore)
2870{ 2814{
2871 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 2815 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2872 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); 2816 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
@@ -2948,19 +2892,26 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm)
2948 if (bcm->current_core->rev >= 5) 2892 if (bcm->current_core->rev >= 5)
2949 bcm43xx_write16(bcm, 0x043C, 0x000C); 2893 bcm43xx_write16(bcm, 0x043C, 0x000C);
2950 2894
2951 if (bcm43xx_using_pio(bcm)) 2895 if (active_wlcore) {
2952 err = bcm43xx_pio_init(bcm); 2896 if (bcm43xx_using_pio(bcm))
2953 else 2897 err = bcm43xx_pio_init(bcm);
2954 err = bcm43xx_dma_init(bcm); 2898 else
2955 if (err) 2899 err = bcm43xx_dma_init(bcm);
2956 goto err_chip_cleanup; 2900 if (err)
2901 goto err_chip_cleanup;
2902 }
2957 bcm43xx_write16(bcm, 0x0612, 0x0050); 2903 bcm43xx_write16(bcm, 0x0612, 0x0050);
2958 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); 2904 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
2959 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); 2905 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
2960 2906
2961 bcm43xx_mac_enable(bcm); 2907 if (active_wlcore) {
2962 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); 2908 if (radio->initial_channel != 0xFF)
2909 bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0);
2910 }
2963 2911
2912 /* Don't enable MAC/IRQ here, as it will race with the IRQ handler.
2913 * We enable it later.
2914 */
2964 bcm->current_core->initialized = 1; 2915 bcm->current_core->initialized = 1;
2965out: 2916out:
2966 return err; 2917 return err;
@@ -3075,11 +3026,6 @@ out:
3075 return err; 3026 return err;
3076} 3027}
3077 3028
3078static void bcm43xx_softmac_init(struct bcm43xx_private *bcm)
3079{
3080 ieee80211softmac_start(bcm->net_dev);
3081}
3082
3083static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) 3029static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
3084{ 3030{
3085 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 3031 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
@@ -3281,141 +3227,322 @@ static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
3281 return err; 3227 return err;
3282} 3228}
3283 3229
3284/* This is the opposite of bcm43xx_init_board() */ 3230static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
3285static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3286{ 3231{
3232 int ret = 0;
3287 int i, err; 3233 int i, err;
3234 struct bcm43xx_coreinfo *core;
3288 3235
3289 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{
3290 bcm43xx_sysfs_unregister(bcm); 3264 bcm43xx_sysfs_unregister(bcm);
3291 bcm43xx_periodic_tasks_delete(bcm); 3265 bcm43xx_periodic_tasks_delete(bcm);
3292 3266
3293 bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); 3267 bcm43xx_lock_noirq(bcm);
3268 bcm43xx_shutdown_all_wireless_cores(bcm);
3269 bcm43xx_pctl_set_crystal(bcm, 0);
3270 bcm43xx_unlock_noirq(bcm);
3271}
3294 3272
3295 bcm43xx_rng_exit(bcm); 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);
3326
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 */
3296 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { 3335 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3297 if (!bcm->core_80211[i].available) 3336 core = &(bcm->core_80211[i]);
3298 continue; 3337 wlext = core->priv;
3299 if (!bcm->core_80211[i].initialized) 3338
3339 if (!core->available)
3300 continue; 3340 continue;
3341 assert(wlext == &(bcm->core_80211_ext[i]));
3301 3342
3302 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); 3343 prepare_phydata_for_init(&wlext->phy);
3303 assert(err == 0); 3344 prepare_radiodata_for_init(bcm, &wlext->radio);
3304 bcm43xx_wireless_core_cleanup(bcm);
3305 } 3345 }
3306 3346
3307 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;
3308 3351
3309 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); 3352 /* Noise calculation context */
3310 mutex_unlock(&bcm->mutex); 3353 memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc));
3354
3355 /* Periodic work context */
3356 bcm->periodic_state = 0;
3311} 3357}
3312 3358
3313static 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)
3314{ 3383{
3315 int i, err; 3384 int i, err;
3316 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;
3317 3390
3318 might_sleep(); 3391 might_sleep();
3319 3392
3320 mutex_lock(&bcm->mutex); 3393 if (phytype < 0) {
3321 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 }
3322 3428
3323 bcm->mac_suspended = 1; 3429 /* Reset all data structures. */
3430 prepare_priv_for_init(bcm);
3324 3431
3325 err = bcm43xx_pctl_set_crystal(bcm, 1);
3326 if (err)
3327 goto out;
3328 err = bcm43xx_pctl_init(bcm);
3329 if (err)
3330 goto err_crystal_off;
3331 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST); 3432 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
3332 if (err) 3433 if (err)
3333 goto err_crystal_off; 3434 goto error;
3334 3435
3335 tasklet_enable(&bcm->isr_tasklet); 3436 /* Mark all unused cores "inactive". */
3336 for (i = 0; i < bcm->nr_80211_available; i++) { 3437 for (i = 0; i < bcm->nr_80211_available; i++) {
3337 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); 3438 core = &(bcm->core_80211[i]);
3338 assert(err != -ENODEV); 3439 wlext = core->priv;
3339 if (err)
3340 goto err_80211_unwind;
3341 3440
3342 /* Enable the selected wireless core. 3441 if (core == active_core)
3343 * Connect PHY only on the first core. 3442 continue;
3344 */ 3443 err = bcm43xx_switch_core(bcm, core);
3345 if (!bcm43xx_core_enabled(bcm)) { 3444 if (err) {
3346 if (bcm->nr_80211_available == 1) { 3445 dprintk(KERN_ERR PFX "Could not switch to inactive "
3347 connect_phy = bcm43xx_current_phy(bcm)->connected; 3446 "802.11 core (%d)\n", err);
3348 } else { 3447 goto error;
3349 if (i == 0)
3350 connect_phy = 1;
3351 else
3352 connect_phy = 0;
3353 }
3354 bcm43xx_wireless_core_reset(bcm, connect_phy);
3355 } 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 }
3356 3457
3357 if (i != 0) 3458 /* Now initialize the active 802.11 core. */
3358 bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]); 3459 err = bcm43xx_switch_core(bcm, active_core);
3359 3460 if (err) {
3360 err = bcm43xx_wireless_core_init(bcm); 3461 dprintk(KERN_ERR PFX "Could not switch to active "
3361 if (err) 3462 "802.11 core (%d)\n", err);
3362 goto err_80211_unwind; 3463 goto error;
3464 }
3465 if (adjust_active_sbtmstatelow &&
3466 active_wlext->phy.type == BCM43xx_PHYTYPE_G) {
3467 u32 sbtmstatelow;
3363 3468
3364 if (i != 0) { 3469 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
3365 bcm43xx_mac_suspend(bcm); 3470 sbtmstatelow |= 0x20000000;
3366 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 3471 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
3367 bcm43xx_radio_turn_off(bcm);
3368 }
3369 } 3472 }
3370 bcm->active_80211_core = &bcm->core_80211[0]; 3473 err = wireless_core_up(bcm, 1);
3371 if (bcm->nr_80211_available >= 2) { 3474 if (err) {
3372 bcm43xx_switch_core(bcm, &bcm->core_80211[0]); 3475 dprintk(KERN_ERR PFX "core_up for active 802.11 core "
3373 bcm43xx_mac_enable(bcm); 3476 "failed (%d)\n", err);
3477 goto error;
3374 } 3478 }
3375 err = bcm43xx_rng_init(bcm); 3479 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
3376 if (err) 3480 if (err)
3377 goto err_80211_unwind; 3481 goto error;
3482 bcm->active_80211_core = active_core;
3483
3378 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); 3484 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
3379 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));
3380 dprintk(KERN_INFO PFX "80211 cores initialized\n");
3381 bcm43xx_security_init(bcm); 3486 bcm43xx_security_init(bcm);
3382 bcm43xx_softmac_init(bcm); 3487 ieee80211softmac_start(bcm->net_dev);
3383 3488
3384 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);
3385 3498
3386 if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) { 3499 dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n",
3387 bcm43xx_mac_suspend(bcm); 3500 active_wlext->phy.type);
3388 bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0);
3389 bcm43xx_mac_enable(bcm);
3390 }
3391 3501
3392 /* Initialization of the board is done. Flag it as such. */ 3502 return 0;
3393 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 bcm43xx_lock_noirq(bcm);
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;
3394 3526
3395 bcm43xx_periodic_tasks_setup(bcm); 3527 bcm43xx_periodic_tasks_setup(bcm);
3396 bcm43xx_sysfs_register(bcm); 3528 err = bcm43xx_sysfs_register(bcm);
3397 //FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though... 3529 if (err)
3530 goto err_wlshutdown;
3398 3531
3399 /*FIXME: This should be handled by softmac instead. */ 3532 /*FIXME: This should be handled by softmac instead. */
3400 schedule_work(&bcm->softmac->associnfo.work); 3533 schedule_work(&bcm->softmac->associnfo.work);
3401 3534
3402 assert(err == 0);
3403out: 3535out:
3404 mutex_unlock(&bcm->mutex); 3536 bcm43xx_unlock_noirq(bcm);
3405 3537
3406 return err; 3538 return err;
3407 3539
3408err_80211_unwind: 3540err_wlshutdown:
3409 tasklet_disable(&bcm->isr_tasklet); 3541 bcm43xx_shutdown_all_wireless_cores(bcm);
3410 /* unwind all 80211 initialization */
3411 for (i = 0; i < bcm->nr_80211_available; i++) {
3412 if (!bcm->core_80211[i].initialized)
3413 continue;
3414 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3415 bcm43xx_wireless_core_cleanup(bcm);
3416 }
3417err_crystal_off: 3542err_crystal_off:
3418 bcm43xx_pctl_set_crystal(bcm, 0); 3543 bcm43xx_pctl_set_crystal(bcm, 0);
3544err_tasklet:
3545 tasklet_disable(&bcm->isr_tasklet);
3419 goto out; 3546 goto out;
3420} 3547}
3421 3548
@@ -3797,7 +3924,8 @@ static void bcm43xx_net_poll_controller(struct net_device *net_dev)
3797 unsigned long flags; 3924 unsigned long flags;
3798 3925
3799 local_irq_save(flags); 3926 local_irq_save(flags);
3800 bcm43xx_interrupt_handler(bcm->irq, bcm, NULL); 3927 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
3928 bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
3801 local_irq_restore(flags); 3929 local_irq_restore(flags);
3802} 3930}
3803#endif /* CONFIG_NET_POLL_CONTROLLER */ 3931#endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -3815,7 +3943,7 @@ static int bcm43xx_net_stop(struct net_device *net_dev)
3815 int err; 3943 int err;
3816 3944
3817 ieee80211softmac_stop(net_dev); 3945 ieee80211softmac_stop(net_dev);
3818 err = bcm43xx_disable_interrupts_sync(bcm, NULL); 3946 err = bcm43xx_disable_interrupts_sync(bcm);
3819 assert(!err); 3947 assert(!err);
3820 bcm43xx_free_board(bcm); 3948 bcm43xx_free_board(bcm);
3821 3949
@@ -3957,7 +4085,6 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
3957 bcm43xx_debugfs_remove_device(bcm); 4085 bcm43xx_debugfs_remove_device(bcm);
3958 unregister_netdev(net_dev); 4086 unregister_netdev(net_dev);
3959 bcm43xx_detach_board(bcm); 4087 bcm43xx_detach_board(bcm);
3960 assert(bcm->ucode == NULL);
3961 free_ieee80211softmac(net_dev); 4088 free_ieee80211softmac(net_dev);
3962} 4089}
3963 4090
@@ -3967,47 +4094,25 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
3967static void bcm43xx_chip_reset(void *_bcm) 4094static void bcm43xx_chip_reset(void *_bcm)
3968{ 4095{
3969 struct bcm43xx_private *bcm = _bcm; 4096 struct bcm43xx_private *bcm = _bcm;
3970 struct net_device *net_dev = bcm->net_dev; 4097 struct bcm43xx_phyinfo *phy;
3971 struct pci_dev *pci_dev = bcm->pci_dev;
3972 int err; 4098 int err;
3973 int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
3974 4099
3975 netif_stop_queue(bcm->net_dev); 4100 bcm43xx_lock_noirq(bcm);
3976 tasklet_disable(&bcm->isr_tasklet); 4101 phy = bcm43xx_current_phy(bcm);
4102 err = bcm43xx_select_wireless_core(bcm, phy->type);
4103 bcm43xx_unlock_noirq(bcm);
3977 4104
3978 bcm->firmware_norelease = 1; 4105 printk(KERN_ERR PFX "Controller restart%s\n",
3979 if (was_initialized) 4106 (err == 0) ? "ed" : " failed");
3980 bcm43xx_free_board(bcm);
3981 bcm->firmware_norelease = 0;
3982 bcm43xx_detach_board(bcm);
3983 err = bcm43xx_init_private(bcm, net_dev, pci_dev);
3984 if (err)
3985 goto failure;
3986 err = bcm43xx_attach_board(bcm);
3987 if (err)
3988 goto failure;
3989 if (was_initialized) {
3990 err = bcm43xx_init_board(bcm);
3991 if (err)
3992 goto failure;
3993 }
3994 netif_wake_queue(bcm->net_dev);
3995 printk(KERN_INFO PFX "Controller restarted\n");
3996
3997 return;
3998failure:
3999 printk(KERN_ERR PFX "Controller restart failed\n");
4000} 4107}
4001 4108
4002/* Hard-reset the chip. 4109/* Hard-reset the chip.
4003 * This can be called from interrupt or process context. 4110 * This can be called from interrupt or process context.
4004 * Make sure to _not_ re-enable device interrupts after this has been called. 4111 */
4005*/
4006void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) 4112void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
4007{ 4113{
4114 assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
4008 bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING); 4115 bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING);
4009 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
4010 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
4011 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); 4116 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
4012 INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); 4117 INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
4013 schedule_work(&bcm->restart_work); 4118 schedule_work(&bcm->restart_work);
@@ -4019,18 +4124,16 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
4019{ 4124{
4020 struct net_device *net_dev = pci_get_drvdata(pdev); 4125 struct net_device *net_dev = pci_get_drvdata(pdev);
4021 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 4126 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4022 int try_to_shutdown = 0, err; 4127 int err;
4023 4128
4024 dprintk(KERN_INFO PFX "Suspending...\n"); 4129 dprintk(KERN_INFO PFX "Suspending...\n");
4025 4130
4026 bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
4027 if (bcm->was_initialized)
4028 try_to_shutdown = 1;
4029
4030 netif_device_detach(net_dev); 4131 netif_device_detach(net_dev);
4031 if (try_to_shutdown) { 4132 bcm->was_initialized = 0;
4133 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
4134 bcm->was_initialized = 1;
4032 ieee80211softmac_stop(net_dev); 4135 ieee80211softmac_stop(net_dev);
4033 err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate); 4136 err = bcm43xx_disable_interrupts_sync(bcm);
4034 if (unlikely(err)) { 4137 if (unlikely(err)) {
4035 dprintk(KERN_ERR PFX "Suspend failed.\n"); 4138 dprintk(KERN_ERR PFX "Suspend failed.\n");
4036 return -EAGAIN; 4139 return -EAGAIN;
@@ -4063,17 +4166,14 @@ static int bcm43xx_resume(struct pci_dev *pdev)
4063 pci_restore_state(pdev); 4166 pci_restore_state(pdev);
4064 4167
4065 bcm43xx_chipset_attach(bcm); 4168 bcm43xx_chipset_attach(bcm);
4066 if (bcm->was_initialized) { 4169 if (bcm->was_initialized)
4067 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
4068 err = bcm43xx_init_board(bcm); 4170 err = bcm43xx_init_board(bcm);
4069 }
4070 if (err) { 4171 if (err) {
4071 printk(KERN_ERR PFX "Resume failed!\n"); 4172 printk(KERN_ERR PFX "Resume failed!\n");
4072 return err; 4173 return err;
4073 } 4174 }
4074
4075 netif_device_attach(net_dev); 4175 netif_device_attach(net_dev);
4076 4176
4077 dprintk(KERN_INFO PFX "Device resumed.\n"); 4177 dprintk(KERN_INFO PFX "Device resumed.\n");
4078 4178
4079 return 0; 4179 return 0;