aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2009-09-04 16:51:29 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-09-08 16:31:06 -0400
commit36dbd9548e92268127b0c31b0e121e63e9207108 (patch)
tree41d95c5dd824ea43c5f0055bd790b64d7ba8a33a /drivers/net
parentb275f28535fc774325bb8ad5f664e6c44a8fbc9b (diff)
b43: Use a threaded IRQ handler
Use a threaded IRQ handler to allow locking the mutex and sleeping while executing an interrupt. This removes usage of the irq_lock spinlock, but introduces a new hardirq_lock, which is _only_ used for the PCI/SSB lowlevel hard-irq handler. Sleeping busses (SDIO) will use mutex instead. Signed-off-by: Michael Buesch <mb@bu3sch.de> Tested-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/b43/b43.h23
-rw-r--r--drivers/net/wireless/b43/debugfs.c53
-rw-r--r--drivers/net/wireless/b43/debugfs.h3
-rw-r--r--drivers/net/wireless/b43/dma.c5
-rw-r--r--drivers/net/wireless/b43/main.c319
-rw-r--r--drivers/net/wireless/b43/phy_common.c1
-rw-r--r--drivers/net/wireless/b43/phy_common.h3
-rw-r--r--drivers/net/wireless/b43/phy_g.c7
-rw-r--r--drivers/net/wireless/b43/phy_g.h3
-rw-r--r--drivers/net/wireless/b43/pio.c5
-rw-r--r--drivers/net/wireless/b43/sysfs.c3
11 files changed, 204 insertions, 221 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index a1b3b731935b..d63af926d058 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -616,6 +616,12 @@ struct b43_wl {
616 /* Pointer to the ieee80211 hardware data structure */ 616 /* Pointer to the ieee80211 hardware data structure */
617 struct ieee80211_hw *hw; 617 struct ieee80211_hw *hw;
618 618
619 /* Global driver mutex. Every operation must run with this mutex locked. */
620 struct mutex mutex;
621 /* Hard-IRQ spinlock. This lock protects things used in the hard-IRQ
622 * handler, only. This basically is just the IRQ mask register. */
623 spinlock_t hardirq_lock;
624
619 /* The number of queues that were registered with the mac80211 subsystem 625 /* The number of queues that were registered with the mac80211 subsystem
620 * initially. This is a backup copy of hw->queues in case hw->queues has 626 * initially. This is a backup copy of hw->queues in case hw->queues has
621 * to be dynamically lowered at runtime (Firmware does not support QoS). 627 * to be dynamically lowered at runtime (Firmware does not support QoS).
@@ -623,8 +629,6 @@ struct b43_wl {
623 * from the mac80211 subsystem. */ 629 * from the mac80211 subsystem. */
624 u16 mac80211_initially_registered_queues; 630 u16 mac80211_initially_registered_queues;
625 631
626 struct mutex mutex;
627 spinlock_t irq_lock;
628 /* R/W lock for data transmission. 632 /* R/W lock for data transmission.
629 * Transmissions on 2+ queues can run concurrently, but somebody else 633 * Transmissions on 2+ queues can run concurrently, but somebody else
630 * might sync with TX by write_lock_irqsave()'ing. */ 634 * might sync with TX by write_lock_irqsave()'ing. */
@@ -665,8 +669,7 @@ struct b43_wl {
665 bool radiotap_enabled; 669 bool radiotap_enabled;
666 bool radio_enabled; 670 bool radio_enabled;
667 671
668 /* The beacon we are currently using (AP or IBSS mode). 672 /* The beacon we are currently using (AP or IBSS mode). */
669 * This beacon stuff is protected by the irq_lock. */
670 struct sk_buff *current_beacon; 673 struct sk_buff *current_beacon;
671 bool beacon0_uploaded; 674 bool beacon0_uploaded;
672 bool beacon1_uploaded; 675 bool beacon1_uploaded;
@@ -754,14 +757,6 @@ enum {
754 smp_wmb(); \ 757 smp_wmb(); \
755 } while (0) 758 } while (0)
756 759
757/* XXX--- HOW LOCKING WORKS IN B43 ---XXX
758 *
759 * You should always acquire both, wl->mutex and wl->irq_lock unless:
760 * - You don't need to acquire wl->irq_lock, if the interface is stopped.
761 * - You don't need to acquire wl->mutex in the IRQ handler, IRQ tasklet
762 * and packet TX path (and _ONLY_ there.)
763 */
764
765/* Data structure for one wireless device (802.11 core) */ 760/* Data structure for one wireless device (802.11 core) */
766struct b43_wldev { 761struct b43_wldev {
767 struct ssb_device *dev; 762 struct ssb_device *dev;
@@ -807,14 +802,12 @@ struct b43_wldev {
807 u32 dma_reason[6]; 802 u32 dma_reason[6];
808 /* The currently active generic-interrupt mask. */ 803 /* The currently active generic-interrupt mask. */
809 u32 irq_mask; 804 u32 irq_mask;
805
810 /* Link Quality calculation context. */ 806 /* Link Quality calculation context. */
811 struct b43_noise_calculation noisecalc; 807 struct b43_noise_calculation noisecalc;
812 /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ 808 /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
813 int mac_suspended; 809 int mac_suspended;
814 810
815 /* Interrupt Service Routine tasklet (bottom-half) */
816 struct tasklet_struct isr_tasklet;
817
818 /* Periodic tasks */ 811 /* Periodic tasks */
819 struct delayed_work periodic_work; 812 struct delayed_work periodic_work;
820 unsigned int periodic_state; 813 unsigned int periodic_state;
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 45e3d6af69f5..bf23a3a863fa 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -46,8 +46,6 @@ struct b43_debugfs_fops {
46 struct file_operations fops; 46 struct file_operations fops;
47 /* Offset of struct b43_dfs_file in struct b43_dfsentry */ 47 /* Offset of struct b43_dfs_file in struct b43_dfsentry */
48 size_t file_struct_offset; 48 size_t file_struct_offset;
49 /* Take wl->irq_lock before calling read/write? */
50 bool take_irqlock;
51}; 49};
52 50
53static inline 51static inline
@@ -372,14 +370,12 @@ static ssize_t txstat_read_file(struct b43_wldev *dev,
372{ 370{
373 struct b43_txstatus_log *log = &dev->dfsentry->txstatlog; 371 struct b43_txstatus_log *log = &dev->dfsentry->txstatlog;
374 ssize_t count = 0; 372 ssize_t count = 0;
375 unsigned long flags;
376 int i, idx; 373 int i, idx;
377 struct b43_txstatus *stat; 374 struct b43_txstatus *stat;
378 375
379 spin_lock_irqsave(&log->lock, flags);
380 if (log->end < 0) { 376 if (log->end < 0) {
381 fappend("Nothing transmitted, yet\n"); 377 fappend("Nothing transmitted, yet\n");
382 goto out_unlock; 378 goto out;
383 } 379 }
384 fappend("b43 TX status reports:\n\n" 380 fappend("b43 TX status reports:\n\n"
385 "index | cookie | seq | phy_stat | frame_count | " 381 "index | cookie | seq | phy_stat | frame_count | "
@@ -409,13 +405,11 @@ static ssize_t txstat_read_file(struct b43_wldev *dev,
409 break; 405 break;
410 i++; 406 i++;
411 } 407 }
412out_unlock: 408out:
413 spin_unlock_irqrestore(&log->lock, flags);
414 409
415 return count; 410 return count;
416} 411}
417 412
418/* wl->irq_lock is locked */
419static int restart_write_file(struct b43_wldev *dev, 413static int restart_write_file(struct b43_wldev *dev,
420 const char *buf, size_t count) 414 const char *buf, size_t count)
421{ 415{
@@ -556,12 +550,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
556 goto out_unlock; 550 goto out_unlock;
557 } 551 }
558 memset(buf, 0, bufsize); 552 memset(buf, 0, bufsize);
559 if (dfops->take_irqlock) { 553 ret = dfops->read(dev, buf, bufsize);
560 spin_lock_irq(&dev->wl->irq_lock);
561 ret = dfops->read(dev, buf, bufsize);
562 spin_unlock_irq(&dev->wl->irq_lock);
563 } else
564 ret = dfops->read(dev, buf, bufsize);
565 if (ret <= 0) { 554 if (ret <= 0) {
566 free_pages((unsigned long)buf, buforder); 555 free_pages((unsigned long)buf, buforder);
567 err = ret; 556 err = ret;
@@ -623,12 +612,7 @@ static ssize_t b43_debugfs_write(struct file *file,
623 err = -EFAULT; 612 err = -EFAULT;
624 goto out_freepage; 613 goto out_freepage;
625 } 614 }
626 if (dfops->take_irqlock) { 615 err = dfops->write(dev, buf, count);
627 spin_lock_irq(&dev->wl->irq_lock);
628 err = dfops->write(dev, buf, count);
629 spin_unlock_irq(&dev->wl->irq_lock);
630 } else
631 err = dfops->write(dev, buf, count);
632 if (err) 616 if (err)
633 goto out_freepage; 617 goto out_freepage;
634 618
@@ -641,7 +625,7 @@ out_unlock:
641} 625}
642 626
643 627
644#define B43_DEBUGFS_FOPS(name, _read, _write, _take_irqlock) \ 628#define B43_DEBUGFS_FOPS(name, _read, _write) \
645 static struct b43_debugfs_fops fops_##name = { \ 629 static struct b43_debugfs_fops fops_##name = { \
646 .read = _read, \ 630 .read = _read, \
647 .write = _write, \ 631 .write = _write, \
@@ -652,20 +636,19 @@ out_unlock:
652 }, \ 636 }, \
653 .file_struct_offset = offsetof(struct b43_dfsentry, \ 637 .file_struct_offset = offsetof(struct b43_dfsentry, \
654 file_##name), \ 638 file_##name), \
655 .take_irqlock = _take_irqlock, \
656 } 639 }
657 640
658B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file, 1); 641B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file);
659B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file, 1); 642B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file);
660B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file, 1); 643B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file);
661B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file, 1); 644B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file);
662B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1); 645B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file);
663B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1); 646B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file);
664B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); 647B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file);
665B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); 648B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file);
666B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); 649B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL);
667B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); 650B43_DEBUGFS_FOPS(restart, NULL, restart_write_file);
668B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0); 651B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL);
669 652
670 653
671bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) 654bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
@@ -738,7 +721,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
738 return; 721 return;
739 } 722 }
740 log->end = -1; 723 log->end = -1;
741 spin_lock_init(&log->lock);
742 724
743 dev->dfsentry = e; 725 dev->dfsentry = e;
744 726
@@ -822,7 +804,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev)
822 kfree(e); 804 kfree(e);
823} 805}
824 806
825/* Called with IRQs disabled. */
826void b43_debugfs_log_txstat(struct b43_wldev *dev, 807void b43_debugfs_log_txstat(struct b43_wldev *dev,
827 const struct b43_txstatus *status) 808 const struct b43_txstatus *status)
828{ 809{
@@ -834,14 +815,12 @@ void b43_debugfs_log_txstat(struct b43_wldev *dev,
834 if (!e) 815 if (!e)
835 return; 816 return;
836 log = &e->txstatlog; 817 log = &e->txstatlog;
837 spin_lock(&log->lock); /* IRQs are already disabled. */
838 i = log->end + 1; 818 i = log->end + 1;
839 if (i == B43_NR_LOGGED_TXSTATUS) 819 if (i == B43_NR_LOGGED_TXSTATUS)
840 i = 0; 820 i = 0;
841 log->end = i; 821 log->end = i;
842 cur = &(log->log[i]); 822 cur = &(log->log[i]);
843 memcpy(cur, status, sizeof(*cur)); 823 memcpy(cur, status, sizeof(*cur));
844 spin_unlock(&log->lock);
845} 824}
846 825
847void b43_debugfs_init(void) 826void b43_debugfs_init(void)
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h
index b9d4de4a979c..e47b4b488b04 100644
--- a/drivers/net/wireless/b43/debugfs.h
+++ b/drivers/net/wireless/b43/debugfs.h
@@ -23,9 +23,10 @@ struct dentry;
23#define B43_NR_LOGGED_TXSTATUS 100 23#define B43_NR_LOGGED_TXSTATUS 100
24 24
25struct b43_txstatus_log { 25struct b43_txstatus_log {
26 /* This structure is protected by wl->mutex */
27
26 struct b43_txstatus *log; 28 struct b43_txstatus *log;
27 int end; 29 int end;
28 spinlock_t lock;
29}; 30};
30 31
31struct b43_dfs_file { 32struct b43_dfs_file {
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 289aaf6dfe79..25ced8bdec8f 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1387,7 +1387,6 @@ out_unlock:
1387 return err; 1387 return err;
1388} 1388}
1389 1389
1390/* Called with IRQs disabled. */
1391void b43_dma_handle_txstatus(struct b43_wldev *dev, 1390void b43_dma_handle_txstatus(struct b43_wldev *dev,
1392 const struct b43_txstatus *status) 1391 const struct b43_txstatus *status)
1393{ 1392{
@@ -1402,7 +1401,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
1402 if (unlikely(!ring)) 1401 if (unlikely(!ring))
1403 return; 1402 return;
1404 1403
1405 spin_lock(&ring->lock); /* IRQs are already disabled. */ 1404 spin_lock_irq(&ring->lock);
1406 1405
1407 B43_WARN_ON(!ring->tx); 1406 B43_WARN_ON(!ring->tx);
1408 ops = ring->ops; 1407 ops = ring->ops;
@@ -1463,7 +1462,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
1463 } 1462 }
1464 } 1463 }
1465 1464
1466 spin_unlock(&ring->lock); 1465 spin_unlock_irq(&ring->lock);
1467} 1466}
1468 1467
1469void b43_dma_get_tx_stats(struct b43_wldev *dev, 1468void b43_dma_get_tx_stats(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index ae05f6671149..80b688441ffe 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -291,7 +291,7 @@ static struct ieee80211_supported_band b43_band_2GHz = {
291 291
292static void b43_wireless_core_exit(struct b43_wldev *dev); 292static void b43_wireless_core_exit(struct b43_wldev *dev);
293static int b43_wireless_core_init(struct b43_wldev *dev); 293static int b43_wireless_core_init(struct b43_wldev *dev);
294static void b43_wireless_core_stop(struct b43_wldev *dev); 294static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
295static int b43_wireless_core_start(struct b43_wldev *dev); 295static int b43_wireless_core_start(struct b43_wldev *dev);
296 296
297static int b43_ratelimit(struct b43_wl *wl) 297static int b43_ratelimit(struct b43_wl *wl)
@@ -685,16 +685,6 @@ static void b43_short_slot_timing_disable(struct b43_wldev *dev)
685 b43_set_slot_time(dev, 20); 685 b43_set_slot_time(dev, 20);
686} 686}
687 687
688/* Synchronize IRQ top- and bottom-half.
689 * IRQs must be masked before calling this.
690 * This must not be called with the irq_lock held.
691 */
692static void b43_synchronize_irq(struct b43_wldev *dev)
693{
694 synchronize_irq(dev->dev->irq);
695 tasklet_kill(&dev->isr_tasklet);
696}
697
698/* DummyTransmission function, as documented on 688/* DummyTransmission function, as documented on
699 * http://bcm-v4.sipsolutions.net/802.11/DummyTransmission 689 * http://bcm-v4.sipsolutions.net/802.11/DummyTransmission
700 */ 690 */
@@ -720,8 +710,7 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
720 buffer[0] = 0x000B846E; 710 buffer[0] = 0x000B846E;
721 } 711 }
722 712
723 spin_lock_irq(&wl->irq_lock); 713 write_lock_irq(&wl->tx_lock);
724 write_lock(&wl->tx_lock);
725 714
726 for (i = 0; i < 5; i++) 715 for (i = 0; i < 5; i++)
727 b43_ram_write(dev, i * 4, buffer[i]); 716 b43_ram_write(dev, i * 4, buffer[i]);
@@ -779,8 +768,7 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
779 if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) 768 if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
780 b43_radio_write16(dev, 0x0051, 0x0037); 769 b43_radio_write16(dev, 0x0051, 0x0037);
781 770
782 write_unlock(&wl->tx_lock); 771 write_unlock_irq(&wl->tx_lock);
783 spin_unlock_irq(&wl->irq_lock);
784} 772}
785 773
786static void key_write(struct b43_wldev *dev, 774static void key_write(struct b43_wldev *dev,
@@ -1620,6 +1608,27 @@ static void handle_irq_beacon(struct b43_wldev *dev)
1620 } 1608 }
1621} 1609}
1622 1610
1611static void b43_do_beacon_update_trigger_work(struct b43_wldev *dev)
1612{
1613 u32 old_irq_mask = dev->irq_mask;
1614
1615 /* update beacon right away or defer to irq */
1616 handle_irq_beacon(dev);
1617 if (old_irq_mask != dev->irq_mask) {
1618 /* The handler updated the IRQ mask. */
1619 B43_WARN_ON(!dev->irq_mask);
1620 if (b43_read32(dev, B43_MMIO_GEN_IRQ_MASK)) {
1621 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
1622 } else {
1623 /* Device interrupts are currently disabled. That means
1624 * we just ran the hardirq handler and scheduled the
1625 * IRQ thread. The thread will write the IRQ mask when
1626 * it finished, so there's nothing to do here. Writing
1627 * the mask _here_ would incorrectly re-enable IRQs. */
1628 }
1629 }
1630}
1631
1623static void b43_beacon_update_trigger_work(struct work_struct *work) 1632static void b43_beacon_update_trigger_work(struct work_struct *work)
1624{ 1633{
1625 struct b43_wl *wl = container_of(work, struct b43_wl, 1634 struct b43_wl *wl = container_of(work, struct b43_wl,
@@ -1629,19 +1638,22 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
1629 mutex_lock(&wl->mutex); 1638 mutex_lock(&wl->mutex);
1630 dev = wl->current_dev; 1639 dev = wl->current_dev;
1631 if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { 1640 if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
1632 spin_lock_irq(&wl->irq_lock); 1641 if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) {
1633 /* update beacon right away or defer to irq */ 1642 /* wl->mutex is enough. */
1634 handle_irq_beacon(dev); 1643 b43_do_beacon_update_trigger_work(dev);
1635 /* The handler might have updated the IRQ mask. */ 1644 mmiowb();
1636 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); 1645 } else {
1637 mmiowb(); 1646 spin_lock_irq(&wl->hardirq_lock);
1638 spin_unlock_irq(&wl->irq_lock); 1647 b43_do_beacon_update_trigger_work(dev);
1648 mmiowb();
1649 spin_unlock_irq(&wl->hardirq_lock);
1650 }
1639 } 1651 }
1640 mutex_unlock(&wl->mutex); 1652 mutex_unlock(&wl->mutex);
1641} 1653}
1642 1654
1643/* Asynchronously update the packet templates in template RAM. 1655/* Asynchronously update the packet templates in template RAM.
1644 * Locking: Requires wl->irq_lock to be locked. */ 1656 * Locking: Requires wl->mutex to be locked. */
1645static void b43_update_templates(struct b43_wl *wl) 1657static void b43_update_templates(struct b43_wl *wl)
1646{ 1658{
1647 struct sk_buff *beacon; 1659 struct sk_buff *beacon;
@@ -1778,18 +1790,15 @@ out:
1778 B43_DEBUGIRQ_REASON_REG, B43_DEBUGIRQ_ACK); 1790 B43_DEBUGIRQ_REASON_REG, B43_DEBUGIRQ_ACK);
1779} 1791}
1780 1792
1781/* Interrupt handler bottom-half */ 1793static void b43_do_interrupt_thread(struct b43_wldev *dev)
1782static void b43_interrupt_tasklet(struct b43_wldev *dev)
1783{ 1794{
1784 u32 reason; 1795 u32 reason;
1785 u32 dma_reason[ARRAY_SIZE(dev->dma_reason)]; 1796 u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
1786 u32 merged_dma_reason = 0; 1797 u32 merged_dma_reason = 0;
1787 int i; 1798 int i;
1788 unsigned long flags;
1789
1790 spin_lock_irqsave(&dev->wl->irq_lock, flags);
1791 1799
1792 B43_WARN_ON(b43_status(dev) != B43_STAT_STARTED); 1800 if (unlikely(b43_status(dev) != B43_STAT_STARTED))
1801 return;
1793 1802
1794 reason = dev->irq_reason; 1803 reason = dev->irq_reason;
1795 for (i = 0; i < ARRAY_SIZE(dma_reason); i++) { 1804 for (i = 0; i < ARRAY_SIZE(dma_reason); i++) {
@@ -1822,8 +1831,6 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
1822 dma_reason[2], dma_reason[3], 1831 dma_reason[2], dma_reason[3],
1823 dma_reason[4], dma_reason[5]); 1832 dma_reason[4], dma_reason[5]);
1824 b43_controller_restart(dev, "DMA error"); 1833 b43_controller_restart(dev, "DMA error");
1825 mmiowb();
1826 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
1827 return; 1834 return;
1828 } 1835 }
1829 if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { 1836 if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
@@ -1867,47 +1874,36 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
1867 if (reason & B43_IRQ_TX_OK) 1874 if (reason & B43_IRQ_TX_OK)
1868 handle_irq_transmit_status(dev); 1875 handle_irq_transmit_status(dev);
1869 1876
1877 /* Re-enable interrupts on the device by restoring the current interrupt mask. */
1870 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); 1878 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
1871 mmiowb();
1872 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
1873} 1879}
1874 1880
1875static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason) 1881/* Interrupt thread handler. Handles device interrupts in thread context. */
1882static irqreturn_t b43_interrupt_thread_handler(int irq, void *dev_id)
1876{ 1883{
1877 b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason); 1884 struct b43_wldev *dev = dev_id;
1878 1885
1879 b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]); 1886 mutex_lock(&dev->wl->mutex);
1880 b43_write32(dev, B43_MMIO_DMA1_REASON, dev->dma_reason[1]); 1887 b43_do_interrupt_thread(dev);
1881 b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]); 1888 mmiowb();
1882 b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]); 1889 mutex_unlock(&dev->wl->mutex);
1883 b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]); 1890
1884/* Unused ring 1891 return IRQ_HANDLED;
1885 b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
1886*/
1887} 1892}
1888 1893
1889/* Interrupt handler top-half */ 1894static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
1890static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
1891{ 1895{
1892 irqreturn_t ret = IRQ_NONE;
1893 struct b43_wldev *dev = dev_id;
1894 u32 reason; 1896 u32 reason;
1895 1897
1896 B43_WARN_ON(!dev); 1898 /* This code runs under wl->hardirq_lock, but _only_ on non-SDIO busses.
1899 * On SDIO, this runs under wl->mutex. */
1897 1900
1898 spin_lock(&dev->wl->irq_lock);
1899
1900 if (unlikely(b43_status(dev) < B43_STAT_STARTED)) {
1901 /* This can only happen on shared IRQ lines. */
1902 goto out;
1903 }
1904 reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); 1901 reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
1905 if (reason == 0xffffffff) /* shared IRQ */ 1902 if (reason == 0xffffffff) /* shared IRQ */
1906 goto out; 1903 return IRQ_NONE;
1907 ret = IRQ_HANDLED;
1908 reason &= dev->irq_mask; 1904 reason &= dev->irq_mask;
1909 if (!reason) 1905 if (!reason)
1910 goto out; 1906 return IRQ_HANDLED;
1911 1907
1912 dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) 1908 dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
1913 & 0x0001DC00; 1909 & 0x0001DC00;
@@ -1924,15 +1920,38 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
1924 & 0x0000DC00; 1920 & 0x0000DC00;
1925*/ 1921*/
1926 1922
1927 b43_interrupt_ack(dev, reason); 1923 /* ACK the interrupt. */
1928 /* disable all IRQs. They are enabled again in the bottom half. */ 1924 b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason);
1925 b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]);
1926 b43_write32(dev, B43_MMIO_DMA1_REASON, dev->dma_reason[1]);
1927 b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);
1928 b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);
1929 b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);
1930/* Unused ring
1931 b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
1932*/
1933
1934 /* Disable IRQs on the device. The IRQ thread handler will re-enable them. */
1929 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); 1935 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
1930 /* save the reason code and call our bottom half. */ 1936 /* Save the reason bitmasks for the IRQ thread handler. */
1931 dev->irq_reason = reason; 1937 dev->irq_reason = reason;
1932 tasklet_schedule(&dev->isr_tasklet); 1938
1933out: 1939 return IRQ_WAKE_THREAD;
1940}
1941
1942/* Interrupt handler top-half. This runs with interrupts disabled. */
1943static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
1944{
1945 struct b43_wldev *dev = dev_id;
1946 irqreturn_t ret;
1947
1948 if (unlikely(b43_status(dev) < B43_STAT_STARTED))
1949 return IRQ_NONE;
1950
1951 spin_lock(&dev->wl->hardirq_lock);
1952 ret = b43_do_interrupt(dev);
1934 mmiowb(); 1953 mmiowb();
1935 spin_unlock(&dev->wl->irq_lock); 1954 spin_unlock(&dev->wl->hardirq_lock);
1936 1955
1937 return ret; 1956 return ret;
1938} 1957}
@@ -3038,15 +3057,12 @@ static void b43_security_init(struct b43_wldev *dev)
3038static int b43_rng_read(struct hwrng *rng, u32 *data) 3057static int b43_rng_read(struct hwrng *rng, u32 *data)
3039{ 3058{
3040 struct b43_wl *wl = (struct b43_wl *)rng->priv; 3059 struct b43_wl *wl = (struct b43_wl *)rng->priv;
3041 unsigned long flags;
3042 3060
3043 /* Don't take wl->mutex here, as it could deadlock with 3061 /* FIXME: We need to take wl->mutex here to make sure the device
3044 * hwrng internal locking. It's not needed to take 3062 * is not going away from under our ass. However it could deadlock
3045 * wl->mutex here, anyway. */ 3063 * with hwrng internal locking. */
3046 3064
3047 spin_lock_irqsave(&wl->irq_lock, flags);
3048 *data = b43_read16(wl->current_dev, B43_MMIO_RNG); 3065 *data = b43_read16(wl->current_dev, B43_MMIO_RNG);
3049 spin_unlock_irqrestore(&wl->irq_lock, flags);
3050 3066
3051 return (sizeof(u16)); 3067 return (sizeof(u16));
3052} 3068}
@@ -3283,22 +3299,20 @@ static int b43_op_get_tx_stats(struct ieee80211_hw *hw,
3283 struct ieee80211_tx_queue_stats *stats) 3299 struct ieee80211_tx_queue_stats *stats)
3284{ 3300{
3285 struct b43_wl *wl = hw_to_b43_wl(hw); 3301 struct b43_wl *wl = hw_to_b43_wl(hw);
3286 struct b43_wldev *dev = wl->current_dev; 3302 struct b43_wldev *dev;
3287 unsigned long flags;
3288 int err = -ENODEV; 3303 int err = -ENODEV;
3289 3304
3290 if (!dev) 3305 mutex_lock(&wl->mutex);
3291 goto out; 3306 dev = wl->current_dev;
3292 spin_lock_irqsave(&wl->irq_lock, flags); 3307 if (dev && b43_status(dev) >= B43_STAT_STARTED) {
3293 if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
3294 if (b43_using_pio_transfers(dev)) 3308 if (b43_using_pio_transfers(dev))
3295 b43_pio_get_tx_stats(dev, stats); 3309 b43_pio_get_tx_stats(dev, stats);
3296 else 3310 else
3297 b43_dma_get_tx_stats(dev, stats); 3311 b43_dma_get_tx_stats(dev, stats);
3298 err = 0; 3312 err = 0;
3299 } 3313 }
3300 spin_unlock_irqrestore(&wl->irq_lock, flags); 3314 mutex_unlock(&wl->mutex);
3301out: 3315
3302 return err; 3316 return err;
3303} 3317}
3304 3318
@@ -3306,11 +3320,10 @@ static int b43_op_get_stats(struct ieee80211_hw *hw,
3306 struct ieee80211_low_level_stats *stats) 3320 struct ieee80211_low_level_stats *stats)
3307{ 3321{
3308 struct b43_wl *wl = hw_to_b43_wl(hw); 3322 struct b43_wl *wl = hw_to_b43_wl(hw);
3309 unsigned long flags;
3310 3323
3311 spin_lock_irqsave(&wl->irq_lock, flags); 3324 mutex_lock(&wl->mutex);
3312 memcpy(stats, &wl->ieee_stats, sizeof(*stats)); 3325 memcpy(stats, &wl->ieee_stats, sizeof(*stats));
3313 spin_unlock_irqrestore(&wl->irq_lock, flags); 3326 mutex_unlock(&wl->mutex);
3314 3327
3315 return 0; 3328 return 0;
3316} 3329}
@@ -3322,7 +3335,6 @@ static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
3322 u64 tsf; 3335 u64 tsf;
3323 3336
3324 mutex_lock(&wl->mutex); 3337 mutex_lock(&wl->mutex);
3325 spin_lock_irq(&wl->irq_lock);
3326 dev = wl->current_dev; 3338 dev = wl->current_dev;
3327 3339
3328 if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) 3340 if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED))
@@ -3330,7 +3342,6 @@ static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
3330 else 3342 else
3331 tsf = 0; 3343 tsf = 0;
3332 3344
3333 spin_unlock_irq(&wl->irq_lock);
3334 mutex_unlock(&wl->mutex); 3345 mutex_unlock(&wl->mutex);
3335 3346
3336 return tsf; 3347 return tsf;
@@ -3342,13 +3353,11 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
3342 struct b43_wldev *dev; 3353 struct b43_wldev *dev;
3343 3354
3344 mutex_lock(&wl->mutex); 3355 mutex_lock(&wl->mutex);
3345 spin_lock_irq(&wl->irq_lock);
3346 dev = wl->current_dev; 3356 dev = wl->current_dev;
3347 3357
3348 if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) 3358 if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED))
3349 b43_tsf_write(dev, tsf); 3359 b43_tsf_write(dev, tsf);
3350 3360
3351 spin_unlock_irq(&wl->irq_lock);
3352 mutex_unlock(&wl->mutex); 3361 mutex_unlock(&wl->mutex);
3353} 3362}
3354 3363
@@ -3434,7 +3443,7 @@ static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan)
3434 prev_status = b43_status(down_dev); 3443 prev_status = b43_status(down_dev);
3435 /* Shutdown the currently running core. */ 3444 /* Shutdown the currently running core. */
3436 if (prev_status >= B43_STAT_STARTED) 3445 if (prev_status >= B43_STAT_STARTED)
3437 b43_wireless_core_stop(down_dev); 3446 down_dev = b43_wireless_core_stop(down_dev);
3438 if (prev_status >= B43_STAT_INITIALIZED) 3447 if (prev_status >= B43_STAT_INITIALIZED)
3439 b43_wireless_core_exit(down_dev); 3448 b43_wireless_core_exit(down_dev);
3440 3449
@@ -3498,7 +3507,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
3498 struct b43_wldev *dev; 3507 struct b43_wldev *dev;
3499 struct b43_phy *phy; 3508 struct b43_phy *phy;
3500 struct ieee80211_conf *conf = &hw->conf; 3509 struct ieee80211_conf *conf = &hw->conf;
3501 unsigned long flags;
3502 int antenna; 3510 int antenna;
3503 int err = 0; 3511 int err = 0;
3504 3512
@@ -3529,13 +3537,11 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
3529 3537
3530 /* Adjust the desired TX power level. */ 3538 /* Adjust the desired TX power level. */
3531 if (conf->power_level != 0) { 3539 if (conf->power_level != 0) {
3532 spin_lock_irqsave(&wl->irq_lock, flags);
3533 if (conf->power_level != phy->desired_txpower) { 3540 if (conf->power_level != phy->desired_txpower) {
3534 phy->desired_txpower = conf->power_level; 3541 phy->desired_txpower = conf->power_level;
3535 b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME | 3542 b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME |
3536 B43_TXPWR_IGNORE_TSSI); 3543 B43_TXPWR_IGNORE_TSSI);
3537 } 3544 }
3538 spin_unlock_irqrestore(&wl->irq_lock, flags);
3539 } 3545 }
3540 3546
3541 /* Antennas for RX and management frame TX. */ 3547 /* Antennas for RX and management frame TX. */
@@ -3620,7 +3626,6 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
3620{ 3626{
3621 struct b43_wl *wl = hw_to_b43_wl(hw); 3627 struct b43_wl *wl = hw_to_b43_wl(hw);
3622 struct b43_wldev *dev; 3628 struct b43_wldev *dev;
3623 unsigned long flags;
3624 3629
3625 mutex_lock(&wl->mutex); 3630 mutex_lock(&wl->mutex);
3626 3631
@@ -3630,7 +3635,6 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
3630 3635
3631 B43_WARN_ON(wl->vif != vif); 3636 B43_WARN_ON(wl->vif != vif);
3632 3637
3633 spin_lock_irqsave(&wl->irq_lock, flags);
3634 if (changed & BSS_CHANGED_BSSID) { 3638 if (changed & BSS_CHANGED_BSSID) {
3635 if (conf->bssid) 3639 if (conf->bssid)
3636 memcpy(wl->bssid, conf->bssid, ETH_ALEN); 3640 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
@@ -3648,7 +3652,6 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
3648 if (changed & BSS_CHANGED_BSSID) 3652 if (changed & BSS_CHANGED_BSSID)
3649 b43_write_mac_bssid_templates(dev); 3653 b43_write_mac_bssid_templates(dev);
3650 } 3654 }
3651 spin_unlock_irqrestore(&wl->irq_lock, flags);
3652 3655
3653 b43_mac_suspend(dev); 3656 b43_mac_suspend(dev);
3654 3657
@@ -3683,18 +3686,15 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3683 u8 algorithm; 3686 u8 algorithm;
3684 u8 index; 3687 u8 index;
3685 int err; 3688 int err;
3689 unsigned long flags;
3686 static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 3690 static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
3687 3691
3688 if (modparam_nohwcrypt) 3692 if (modparam_nohwcrypt)
3689 return -ENOSPC; /* User disabled HW-crypto */ 3693 return -ENOSPC; /* User disabled HW-crypto */
3690 3694
3691 mutex_lock(&wl->mutex); 3695 mutex_lock(&wl->mutex);
3692 spin_lock_irq(&wl->irq_lock); 3696 write_lock_irqsave(&wl->tx_lock, flags);
3693 write_lock(&wl->tx_lock); 3697 /* mutex -> Every config operation must take it.
3694 /* Why do we need all this locking here?
3695 * mutex -> Every config operation must take it.
3696 * irq_lock -> We modify the dev->key array, which is accessed
3697 * in the IRQ handlers.
3698 * tx_lock -> We modify the dev->key array, which is accessed 3698 * tx_lock -> We modify the dev->key array, which is accessed
3699 * in the TX handler. 3699 * in the TX handler.
3700 */ 3700 */
@@ -3789,8 +3789,7 @@ out_unlock:
3789 sta ? sta->addr : bcast_addr); 3789 sta ? sta->addr : bcast_addr);
3790 b43_dump_keymemory(dev); 3790 b43_dump_keymemory(dev);
3791 } 3791 }
3792 write_unlock(&wl->tx_lock); 3792 write_unlock_irqrestore(&wl->tx_lock, flags);
3793 spin_unlock_irq(&wl->irq_lock);
3794 mutex_unlock(&wl->mutex); 3793 mutex_unlock(&wl->mutex);
3795 3794
3796 return err; 3795 return err;
@@ -3801,15 +3800,15 @@ static void b43_op_configure_filter(struct ieee80211_hw *hw,
3801 u64 multicast) 3800 u64 multicast)
3802{ 3801{
3803 struct b43_wl *wl = hw_to_b43_wl(hw); 3802 struct b43_wl *wl = hw_to_b43_wl(hw);
3804 struct b43_wldev *dev = wl->current_dev; 3803 struct b43_wldev *dev;
3805 unsigned long flags;
3806 3804
3805 mutex_lock(&wl->mutex);
3806 dev = wl->current_dev;
3807 if (!dev) { 3807 if (!dev) {
3808 *fflags = 0; 3808 *fflags = 0;
3809 return; 3809 goto out_unlock;
3810 } 3810 }
3811 3811
3812 spin_lock_irqsave(&wl->irq_lock, flags);
3813 *fflags &= FIF_PROMISC_IN_BSS | 3812 *fflags &= FIF_PROMISC_IN_BSS |
3814 FIF_ALLMULTI | 3813 FIF_ALLMULTI |
3815 FIF_FCSFAIL | 3814 FIF_FCSFAIL |
@@ -3830,41 +3829,66 @@ static void b43_op_configure_filter(struct ieee80211_hw *hw,
3830 3829
3831 if (changed && b43_status(dev) >= B43_STAT_INITIALIZED) 3830 if (changed && b43_status(dev) >= B43_STAT_INITIALIZED)
3832 b43_adjust_opmode(dev); 3831 b43_adjust_opmode(dev);
3833 spin_unlock_irqrestore(&wl->irq_lock, flags); 3832
3833out_unlock:
3834 mutex_unlock(&wl->mutex);
3834} 3835}
3835 3836
3836/* Locking: wl->mutex */ 3837/* Locking: wl->mutex
3837static void b43_wireless_core_stop(struct b43_wldev *dev) 3838 * Returns the current dev. This might be different from the passed in dev,
3839 * because the core might be gone away while we unlocked the mutex. */
3840static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
3838{ 3841{
3839 struct b43_wl *wl = dev->wl; 3842 struct b43_wl *wl = dev->wl;
3840 unsigned long flags; 3843 struct b43_wldev *orig_dev;
3841 3844
3842 if (b43_status(dev) < B43_STAT_STARTED) 3845redo:
3843 return; 3846 if (!dev || b43_status(dev) < B43_STAT_STARTED)
3847 return dev;
3844 3848
3845 /* Disable and sync interrupts. We must do this before than 3849 /* Disable periodic work. Unlock to avoid deadlocks. */
3846 * setting the status to INITIALIZED, as the interrupt handler 3850 mutex_unlock(&wl->mutex);
3847 * won't care about IRQs then. */ 3851 cancel_delayed_work_sync(&dev->periodic_work);
3848 spin_lock_irqsave(&wl->irq_lock, flags); 3852 mutex_lock(&wl->mutex);
3849 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); 3853 dev = wl->current_dev;
3850 b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */ 3854 if (!dev || b43_status(dev) < B43_STAT_STARTED) {
3851 spin_unlock_irqrestore(&wl->irq_lock, flags); 3855 /* Whoops, aliens ate up the device while we were unlocked. */
3852 b43_synchronize_irq(dev); 3856 return dev;
3857 }
3853 3858
3854 write_lock_irqsave(&wl->tx_lock, flags); 3859 /* Disable interrupts on the device. */
3855 b43_set_status(dev, B43_STAT_INITIALIZED); 3860 b43_set_status(dev, B43_STAT_INITIALIZED);
3856 write_unlock_irqrestore(&wl->tx_lock, flags); 3861 if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) {
3857 3862 /* wl->mutex is locked. That is enough. */
3858 b43_pio_stop(dev); 3863 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
3864 b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
3865 } else {
3866 spin_lock_irq(&wl->hardirq_lock);
3867 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
3868 b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
3869 spin_unlock_irq(&wl->hardirq_lock);
3870 }
3871 /* Synchronize the interrupt handlers. Unlock to avoid deadlocks. */
3872 orig_dev = dev;
3859 mutex_unlock(&wl->mutex); 3873 mutex_unlock(&wl->mutex);
3860 /* Must unlock as it would otherwise deadlock. No races here. 3874 synchronize_irq(dev->dev->irq);
3861 * Cancel the possibly running self-rearming periodic work. */
3862 cancel_delayed_work_sync(&dev->periodic_work);
3863 mutex_lock(&wl->mutex); 3875 mutex_lock(&wl->mutex);
3876 dev = wl->current_dev;
3877 if (!dev)
3878 return dev;
3879 if (dev != orig_dev) {
3880 if (b43_status(dev) >= B43_STAT_STARTED)
3881 goto redo;
3882 return dev;
3883 }
3884 B43_WARN_ON(b43_read32(dev, B43_MMIO_GEN_IRQ_MASK));
3864 3885
3886 b43_pio_stop(dev);
3865 b43_mac_suspend(dev); 3887 b43_mac_suspend(dev);
3866 free_irq(dev->dev->irq, dev); 3888 free_irq(dev->dev->irq, dev);
3867 b43dbg(wl, "Wireless interface stopped\n"); 3889 b43dbg(wl, "Wireless interface stopped\n");
3890
3891 return dev;
3868} 3892}
3869 3893
3870/* Locking: wl->mutex */ 3894/* Locking: wl->mutex */
@@ -3875,8 +3899,9 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
3875 B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); 3899 B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
3876 3900
3877 drain_txstatus_queue(dev); 3901 drain_txstatus_queue(dev);
3878 err = request_irq(dev->dev->irq, b43_interrupt_handler, 3902 err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
3879 IRQF_SHARED, KBUILD_MODNAME, dev); 3903 b43_interrupt_thread_handler,
3904 IRQF_SHARED, KBUILD_MODNAME, dev);
3880 if (err) { 3905 if (err) {
3881 b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq); 3906 b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
3882 goto out; 3907 goto out;
@@ -4155,8 +4180,8 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
4155{ 4180{
4156 u32 macctl; 4181 u32 macctl;
4157 4182
4158 B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED); 4183 B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED);
4159 if (b43_status(dev) != B43_STAT_INITIALIZED) 4184 if (!dev || b43_status(dev) != B43_STAT_INITIALIZED)
4160 return; 4185 return;
4161 b43_set_status(dev, B43_STAT_UNINIT); 4186 b43_set_status(dev, B43_STAT_UNINIT);
4162 4187
@@ -4309,7 +4334,6 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
4309{ 4334{
4310 struct b43_wl *wl = hw_to_b43_wl(hw); 4335 struct b43_wl *wl = hw_to_b43_wl(hw);
4311 struct b43_wldev *dev; 4336 struct b43_wldev *dev;
4312 unsigned long flags;
4313 int err = -EOPNOTSUPP; 4337 int err = -EOPNOTSUPP;
4314 4338
4315 /* TODO: allow WDS/AP devices to coexist */ 4339 /* TODO: allow WDS/AP devices to coexist */
@@ -4333,12 +4357,10 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
4333 wl->if_type = conf->type; 4357 wl->if_type = conf->type;
4334 memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); 4358 memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
4335 4359
4336 spin_lock_irqsave(&wl->irq_lock, flags);
4337 b43_adjust_opmode(dev); 4360 b43_adjust_opmode(dev);
4338 b43_set_pretbtt(dev); 4361 b43_set_pretbtt(dev);
4339 b43_set_synth_pu_delay(dev, 0); 4362 b43_set_synth_pu_delay(dev, 0);
4340 b43_upload_card_macaddress(dev); 4363 b43_upload_card_macaddress(dev);
4341 spin_unlock_irqrestore(&wl->irq_lock, flags);
4342 4364
4343 err = 0; 4365 err = 0;
4344 out_mutex_unlock: 4366 out_mutex_unlock:
@@ -4352,7 +4374,6 @@ static void b43_op_remove_interface(struct ieee80211_hw *hw,
4352{ 4374{
4353 struct b43_wl *wl = hw_to_b43_wl(hw); 4375 struct b43_wl *wl = hw_to_b43_wl(hw);
4354 struct b43_wldev *dev = wl->current_dev; 4376 struct b43_wldev *dev = wl->current_dev;
4355 unsigned long flags;
4356 4377
4357 b43dbg(wl, "Removing Interface type %d\n", conf->type); 4378 b43dbg(wl, "Removing Interface type %d\n", conf->type);
4358 4379
@@ -4364,11 +4385,9 @@ static void b43_op_remove_interface(struct ieee80211_hw *hw,
4364 4385
4365 wl->operating = 0; 4386 wl->operating = 0;
4366 4387
4367 spin_lock_irqsave(&wl->irq_lock, flags);
4368 b43_adjust_opmode(dev); 4388 b43_adjust_opmode(dev);
4369 memset(wl->mac_addr, 0, ETH_ALEN); 4389 memset(wl->mac_addr, 0, ETH_ALEN);
4370 b43_upload_card_macaddress(dev); 4390 b43_upload_card_macaddress(dev);
4371 spin_unlock_irqrestore(&wl->irq_lock, flags);
4372 4391
4373 mutex_unlock(&wl->mutex); 4392 mutex_unlock(&wl->mutex);
4374} 4393}
@@ -4428,10 +4447,15 @@ static void b43_op_stop(struct ieee80211_hw *hw)
4428 cancel_work_sync(&(wl->beacon_update_trigger)); 4447 cancel_work_sync(&(wl->beacon_update_trigger));
4429 4448
4430 mutex_lock(&wl->mutex); 4449 mutex_lock(&wl->mutex);
4431 if (b43_status(dev) >= B43_STAT_STARTED) 4450 if (b43_status(dev) >= B43_STAT_STARTED) {
4432 b43_wireless_core_stop(dev); 4451 dev = b43_wireless_core_stop(dev);
4452 if (!dev)
4453 goto out_unlock;
4454 }
4433 b43_wireless_core_exit(dev); 4455 b43_wireless_core_exit(dev);
4434 wl->radio_enabled = 0; 4456 wl->radio_enabled = 0;
4457
4458out_unlock:
4435 mutex_unlock(&wl->mutex); 4459 mutex_unlock(&wl->mutex);
4436 4460
4437 cancel_work_sync(&(wl->txpower_adjust_work)); 4461 cancel_work_sync(&(wl->txpower_adjust_work));
@@ -4441,11 +4465,10 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw,
4441 struct ieee80211_sta *sta, bool set) 4465 struct ieee80211_sta *sta, bool set)
4442{ 4466{
4443 struct b43_wl *wl = hw_to_b43_wl(hw); 4467 struct b43_wl *wl = hw_to_b43_wl(hw);
4444 unsigned long flags;
4445 4468
4446 spin_lock_irqsave(&wl->irq_lock, flags); 4469 mutex_lock(&wl->mutex);
4447 b43_update_templates(wl); 4470 b43_update_templates(wl);
4448 spin_unlock_irqrestore(&wl->irq_lock, flags); 4471 mutex_unlock(&wl->mutex);
4449 4472
4450 return 0; 4473 return 0;
4451} 4474}
@@ -4526,8 +4549,13 @@ static void b43_chip_reset(struct work_struct *work)
4526 4549
4527 prev_status = b43_status(dev); 4550 prev_status = b43_status(dev);
4528 /* Bring the device down... */ 4551 /* Bring the device down... */
4529 if (prev_status >= B43_STAT_STARTED) 4552 if (prev_status >= B43_STAT_STARTED) {
4530 b43_wireless_core_stop(dev); 4553 dev = b43_wireless_core_stop(dev);
4554 if (!dev) {
4555 err = -ENODEV;
4556 goto out;
4557 }
4558 }
4531 if (prev_status >= B43_STAT_INITIALIZED) 4559 if (prev_status >= B43_STAT_INITIALIZED)
4532 b43_wireless_core_exit(dev); 4560 b43_wireless_core_exit(dev);
4533 4561
@@ -4742,9 +4770,6 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
4742 wldev->wl = wl; 4770 wldev->wl = wl;
4743 b43_set_status(wldev, B43_STAT_UNINIT); 4771 b43_set_status(wldev, B43_STAT_UNINIT);
4744 wldev->bad_frames_preempt = modparam_bad_frames_preempt; 4772 wldev->bad_frames_preempt = modparam_bad_frames_preempt;
4745 tasklet_init(&wldev->isr_tasklet,
4746 (void (*)(unsigned long))b43_interrupt_tasklet,
4747 (unsigned long)wldev);
4748 INIT_LIST_HEAD(&wldev->list); 4773 INIT_LIST_HEAD(&wldev->list);
4749 4774
4750 err = b43_wireless_core_attach(wldev); 4775 err = b43_wireless_core_attach(wldev);
@@ -4841,11 +4866,11 @@ static int b43_wireless_init(struct ssb_device *dev)
4841 4866
4842 /* Initialize struct b43_wl */ 4867 /* Initialize struct b43_wl */
4843 wl->hw = hw; 4868 wl->hw = hw;
4844 spin_lock_init(&wl->irq_lock);
4845 rwlock_init(&wl->tx_lock); 4869 rwlock_init(&wl->tx_lock);
4846 spin_lock_init(&wl->leds_lock); 4870 spin_lock_init(&wl->leds_lock);
4847 spin_lock_init(&wl->shm_lock); 4871 spin_lock_init(&wl->shm_lock);
4848 mutex_init(&wl->mutex); 4872 mutex_init(&wl->mutex);
4873 spin_lock_init(&wl->hardirq_lock);
4849 INIT_LIST_HEAD(&wl->devlist); 4874 INIT_LIST_HEAD(&wl->devlist);
4850 INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); 4875 INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
4851 INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); 4876 INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);
@@ -4946,8 +4971,8 @@ static int b43_suspend(struct ssb_device *dev, pm_message_t state)
4946 wldev->suspend_in_progress = true; 4971 wldev->suspend_in_progress = true;
4947 wldev->suspend_init_status = b43_status(wldev); 4972 wldev->suspend_init_status = b43_status(wldev);
4948 if (wldev->suspend_init_status >= B43_STAT_STARTED) 4973 if (wldev->suspend_init_status >= B43_STAT_STARTED)
4949 b43_wireless_core_stop(wldev); 4974 wldev = b43_wireless_core_stop(wldev);
4950 if (wldev->suspend_init_status >= B43_STAT_INITIALIZED) 4975 if (wldev && wldev->suspend_init_status >= B43_STAT_INITIALIZED)
4951 b43_wireless_core_exit(wldev); 4976 b43_wireless_core_exit(wldev);
4952 mutex_unlock(&wl->mutex); 4977 mutex_unlock(&wl->mutex);
4953 4978
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 6e704becda6f..75b26e175e8f 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -347,7 +347,6 @@ void b43_phy_txpower_adjust_work(struct work_struct *work)
347 mutex_unlock(&wl->mutex); 347 mutex_unlock(&wl->mutex);
348} 348}
349 349
350/* Called with wl->irq_lock locked */
351void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags) 350void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
352{ 351{
353 struct b43_phy *phy = &dev->phy; 352 struct b43_phy *phy = &dev->phy;
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 28e384633c34..9edd4e8e0c85 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -131,7 +131,7 @@ enum b43_txpwr_result {
131 * If the parameter "ignore_tssi" is true, the TSSI values should 131 * If the parameter "ignore_tssi" is true, the TSSI values should
132 * be ignored and a recalculation of the power settings should be 132 * be ignored and a recalculation of the power settings should be
133 * done even if the TSSI values did not change. 133 * done even if the TSSI values did not change.
134 * This callback is called with wl->irq_lock held and must not sleep. 134 * This function may sleep, but should not.
135 * Must not be NULL. 135 * Must not be NULL.
136 * @adjust_txpower: Write the previously calculated TX power settings 136 * @adjust_txpower: Write the previously calculated TX power settings
137 * (from @recalc_txpower) to the hardware. 137 * (from @recalc_txpower) to the hardware.
@@ -379,7 +379,6 @@ void b43_software_rfkill(struct b43_wldev *dev, bool blocked);
379 * 379 *
380 * Compare the current TX power output to the desired power emission 380 * Compare the current TX power output to the desired power emission
381 * and schedule an adjustment in case it mismatches. 381 * and schedule an adjustment in case it mismatches.
382 * Requires wl->irq_lock locked.
383 * 382 *
384 * @flags: OR'ed enum b43_phy_txpower_check_flags flags. 383 * @flags: OR'ed enum b43_phy_txpower_check_flags flags.
385 * See the docs below. 384 * See the docs below.
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c
index 5afa4df0b02f..382826a8da82 100644
--- a/drivers/net/wireless/b43/phy_g.c
+++ b/drivers/net/wireless/b43/phy_g.c
@@ -2823,8 +2823,6 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
2823 2823
2824 b43_mac_suspend(dev); 2824 b43_mac_suspend(dev);
2825 2825
2826 spin_lock_irq(&dev->wl->irq_lock);
2827
2828 /* Calculate the new attenuation values. */ 2826 /* Calculate the new attenuation values. */
2829 bbatt = gphy->bbatt.att; 2827 bbatt = gphy->bbatt.att;
2830 bbatt += gphy->bbatt_delta; 2828 bbatt += gphy->bbatt_delta;
@@ -2864,11 +2862,6 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
2864 gphy->rfatt.att = rfatt; 2862 gphy->rfatt.att = rfatt;
2865 gphy->bbatt.att = bbatt; 2863 gphy->bbatt.att = bbatt;
2866 2864
2867 /* We drop the lock early, so we can sleep during hardware
2868 * adjustment. Possible races with op_recalc_txpower are harmless,
2869 * as we will be called once again in case we raced. */
2870 spin_unlock_irq(&dev->wl->irq_lock);
2871
2872 if (b43_debug(dev, B43_DBG_XMITPOWER)) 2865 if (b43_debug(dev, B43_DBG_XMITPOWER))
2873 b43dbg(dev->wl, "Adjusting TX power\n"); 2866 b43dbg(dev->wl, "Adjusting TX power\n");
2874 2867
diff --git a/drivers/net/wireless/b43/phy_g.h b/drivers/net/wireless/b43/phy_g.h
index 718947fd41ae..8569fdd4c6be 100644
--- a/drivers/net/wireless/b43/phy_g.h
+++ b/drivers/net/wireless/b43/phy_g.h
@@ -141,8 +141,7 @@ struct b43_phy_g {
141 int tgt_idle_tssi; 141 int tgt_idle_tssi;
142 /* Current idle TSSI */ 142 /* Current idle TSSI */
143 int cur_idle_tssi; 143 int cur_idle_tssi;
144 /* The current average TSSI. 144 /* The current average TSSI. */
145 * Needs irq_lock, as it's updated in the IRQ path. */
146 u8 average_tssi; 145 u8 average_tssi;
147 /* Current TX power level attenuation control values */ 146 /* Current TX power level attenuation control values */
148 struct b43_bbatt bbatt; 147 struct b43_bbatt bbatt;
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 3fd653c78b10..ce6f36eb88ca 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -570,7 +570,6 @@ out_unlock:
570 return err; 570 return err;
571} 571}
572 572
573/* Called with IRQs disabled. */
574void b43_pio_handle_txstatus(struct b43_wldev *dev, 573void b43_pio_handle_txstatus(struct b43_wldev *dev,
575 const struct b43_txstatus *status) 574 const struct b43_txstatus *status)
576{ 575{
@@ -584,7 +583,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
584 return; 583 return;
585 B43_WARN_ON(!pack); 584 B43_WARN_ON(!pack);
586 585
587 spin_lock(&q->lock); /* IRQs are already disabled. */ 586 spin_lock_irq(&q->lock);
588 587
589 info = IEEE80211_SKB_CB(pack->skb); 588 info = IEEE80211_SKB_CB(pack->skb);
590 589
@@ -604,7 +603,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
604 q->stopped = 0; 603 q->stopped = 0;
605 } 604 }
606 605
607 spin_unlock(&q->lock); 606 spin_unlock_irq(&q->lock);
608} 607}
609 608
610void b43_pio_get_tx_stats(struct b43_wldev *dev, 609void b43_pio_get_tx_stats(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
index 5adaa3692d75..f1ae4e05a32c 100644
--- a/drivers/net/wireless/b43/sysfs.c
+++ b/drivers/net/wireless/b43/sysfs.c
@@ -94,7 +94,6 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
94 const char *buf, size_t count) 94 const char *buf, size_t count)
95{ 95{
96 struct b43_wldev *wldev = dev_to_b43_wldev(dev); 96 struct b43_wldev *wldev = dev_to_b43_wldev(dev);
97 unsigned long flags;
98 int err; 97 int err;
99 int mode; 98 int mode;
100 99
@@ -120,7 +119,6 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
120 } 119 }
121 120
122 mutex_lock(&wldev->wl->mutex); 121 mutex_lock(&wldev->wl->mutex);
123 spin_lock_irqsave(&wldev->wl->irq_lock, flags);
124 122
125 if (wldev->phy.ops->interf_mitigation) { 123 if (wldev->phy.ops->interf_mitigation) {
126 err = wldev->phy.ops->interf_mitigation(wldev, mode); 124 err = wldev->phy.ops->interf_mitigation(wldev, mode);
@@ -132,7 +130,6 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
132 err = -ENOSYS; 130 err = -ENOSYS;
133 131
134 mmiowb(); 132 mmiowb();
135 spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
136 mutex_unlock(&wldev->wl->mutex); 133 mutex_unlock(&wldev->wl->mutex);
137 134
138 return err ? err : count; 135 return err ? err : count;