diff options
author | Michael Buesch <mb@bu3sch.de> | 2009-09-04 16:51:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-09-08 16:31:06 -0400 |
commit | 36dbd9548e92268127b0c31b0e121e63e9207108 (patch) | |
tree | 41d95c5dd824ea43c5f0055bd790b64d7ba8a33a /drivers/net/wireless | |
parent | b275f28535fc774325bb8ad5f664e6c44a8fbc9b (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/wireless')
-rw-r--r-- | drivers/net/wireless/b43/b43.h | 23 | ||||
-rw-r--r-- | drivers/net/wireless/b43/debugfs.c | 53 | ||||
-rw-r--r-- | drivers/net/wireless/b43/debugfs.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/b43/dma.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 319 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_common.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_common.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_g.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_g.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/b43/pio.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/b43/sysfs.c | 3 |
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) */ |
766 | struct b43_wldev { | 761 | struct 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 | ||
53 | static inline | 51 | static 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 | } |
412 | out_unlock: | 408 | out: |
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 */ | ||
419 | static int restart_write_file(struct b43_wldev *dev, | 413 | static 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 | ||
658 | B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file, 1); | 641 | B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file); |
659 | B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file, 1); | 642 | B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file); |
660 | B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file, 1); | 643 | B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file); |
661 | B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file, 1); | 644 | B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file); |
662 | B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1); | 645 | B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file); |
663 | B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1); | 646 | B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file); |
664 | B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); | 647 | B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file); |
665 | B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); | 648 | B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file); |
666 | B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); | 649 | B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL); |
667 | B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); | 650 | B43_DEBUGFS_FOPS(restart, NULL, restart_write_file); |
668 | B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0); | 651 | B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL); |
669 | 652 | ||
670 | 653 | ||
671 | bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) | 654 | bool 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. */ | ||
826 | void b43_debugfs_log_txstat(struct b43_wldev *dev, | 807 | void 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 | ||
847 | void b43_debugfs_init(void) | 826 | void 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 | ||
25 | struct b43_txstatus_log { | 25 | struct 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 | ||
31 | struct b43_dfs_file { | 32 | struct 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. */ | ||
1391 | void b43_dma_handle_txstatus(struct b43_wldev *dev, | 1390 | void 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 | ||
1469 | void b43_dma_get_tx_stats(struct b43_wldev *dev, | 1468 | void 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 | ||
292 | static void b43_wireless_core_exit(struct b43_wldev *dev); | 292 | static void b43_wireless_core_exit(struct b43_wldev *dev); |
293 | static int b43_wireless_core_init(struct b43_wldev *dev); | 293 | static int b43_wireless_core_init(struct b43_wldev *dev); |
294 | static void b43_wireless_core_stop(struct b43_wldev *dev); | 294 | static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev); |
295 | static int b43_wireless_core_start(struct b43_wldev *dev); | 295 | static int b43_wireless_core_start(struct b43_wldev *dev); |
296 | 296 | ||
297 | static int b43_ratelimit(struct b43_wl *wl) | 297 | static 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 | */ | ||
692 | static 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 | ||
786 | static void key_write(struct b43_wldev *dev, | 774 | static 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 | ||
1611 | static 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 | |||
1623 | static void b43_beacon_update_trigger_work(struct work_struct *work) | 1632 | static 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. */ |
1645 | static void b43_update_templates(struct b43_wl *wl) | 1657 | static 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 */ | 1793 | static void b43_do_interrupt_thread(struct b43_wldev *dev) |
1782 | static 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 | ||
1875 | static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason) | 1881 | /* Interrupt thread handler. Handles device interrupts in thread context. */ |
1882 | static 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 */ | 1894 | static irqreturn_t b43_do_interrupt(struct b43_wldev *dev) |
1890 | static 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 | |
1933 | out: | 1939 | return IRQ_WAKE_THREAD; |
1940 | } | ||
1941 | |||
1942 | /* Interrupt handler top-half. This runs with interrupts disabled. */ | ||
1943 | static 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) | |||
3038 | static int b43_rng_read(struct hwrng *rng, u32 *data) | 3057 | static 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); |
3301 | out: | 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 | |
3833 | out_unlock: | ||
3834 | mutex_unlock(&wl->mutex); | ||
3834 | } | 3835 | } |
3835 | 3836 | ||
3836 | /* Locking: wl->mutex */ | 3837 | /* Locking: wl->mutex |
3837 | static 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. */ | ||
3840 | static 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) | 3845 | redo: |
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 | |||
4458 | out_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 */ | ||
351 | void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags) | 350 | void 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. */ | ||
574 | void b43_pio_handle_txstatus(struct b43_wldev *dev, | 573 | void 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 | ||
610 | void b43_pio_get_tx_stats(struct b43_wldev *dev, | 609 | void 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; |