diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-06-20 04:46:02 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-06-20 04:46:02 -0400 |
commit | 4b2d9cf00962d0a0e697f887f3ecaa155cbde555 (patch) | |
tree | 3a64ad0825e82c3df0b4d84c412c647c19e34afb /drivers/net | |
parent | 4c1234ff24dd8dc2d9020d6315d91a71339be114 (diff) | |
parent | 89c318ed3985da1271e00ad586f2dce8a6e75656 (diff) |
Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx.h | 100 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 33 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_main.c | 221 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 44 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_pio.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 38 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 107 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2200.c | 41 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2200.h | 1 |
11 files changed, 398 insertions, 213 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index e66fdb1f3cfd..d8f917c21ea4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h | |||
@@ -636,6 +636,17 @@ struct bcm43xx_key { | |||
636 | u8 algorithm; | 636 | u8 algorithm; |
637 | }; | 637 | }; |
638 | 638 | ||
639 | /* Driver initialization status. */ | ||
640 | enum { | ||
641 | BCM43xx_STAT_UNINIT, /* Uninitialized. */ | ||
642 | BCM43xx_STAT_INITIALIZING, /* init_board() in progress. */ | ||
643 | BCM43xx_STAT_INITIALIZED, /* Fully operational. */ | ||
644 | BCM43xx_STAT_SHUTTINGDOWN, /* free_board() in progress. */ | ||
645 | BCM43xx_STAT_RESTARTING, /* controller_restart() called. */ | ||
646 | }; | ||
647 | #define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status) | ||
648 | #define bcm43xx_set_status(bcm, stat) atomic_set(&(bcm)->init_status, (stat)) | ||
649 | |||
639 | struct bcm43xx_private { | 650 | struct bcm43xx_private { |
640 | struct ieee80211_device *ieee; | 651 | struct ieee80211_device *ieee; |
641 | struct ieee80211softmac_device *softmac; | 652 | struct ieee80211softmac_device *softmac; |
@@ -646,18 +657,17 @@ struct bcm43xx_private { | |||
646 | 657 | ||
647 | void __iomem *mmio_addr; | 658 | void __iomem *mmio_addr; |
648 | 659 | ||
649 | /* Do not use the lock directly. Use the bcm43xx_lock* helper | 660 | /* Locking, see "theory of locking" text below. */ |
650 | * functions, to be MMIO-safe. */ | 661 | spinlock_t irq_lock; |
651 | spinlock_t _lock; | 662 | struct mutex mutex; |
652 | 663 | ||
653 | /* Driver status flags. */ | 664 | /* Driver initialization status BCM43xx_STAT_*** */ |
654 | u32 initialized:1, /* init_board() succeed */ | 665 | atomic_t init_status; |
655 | was_initialized:1, /* for PCI suspend/resume. */ | 666 | |
656 | shutting_down:1, /* free_board() in progress */ | 667 | u16 was_initialized:1, /* for PCI suspend/resume. */ |
657 | __using_pio:1, /* Internal, use bcm43xx_using_pio(). */ | 668 | __using_pio:1, /* Internal, use bcm43xx_using_pio(). */ |
658 | bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */ | 669 | bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */ |
659 | reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */ | 670 | reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */ |
660 | powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */ | ||
661 | short_preamble:1, /* TRUE, if short preamble is enabled. */ | 671 | short_preamble:1, /* TRUE, if short preamble is enabled. */ |
662 | firmware_norelease:1; /* Do not release the firmware. Used on suspend. */ | 672 | firmware_norelease:1; /* Do not release the firmware. Used on suspend. */ |
663 | 673 | ||
@@ -721,7 +731,7 @@ struct bcm43xx_private { | |||
721 | struct tasklet_struct isr_tasklet; | 731 | struct tasklet_struct isr_tasklet; |
722 | 732 | ||
723 | /* Periodic tasks */ | 733 | /* Periodic tasks */ |
724 | struct timer_list periodic_tasks; | 734 | struct work_struct periodic_work; |
725 | unsigned int periodic_state; | 735 | unsigned int periodic_state; |
726 | 736 | ||
727 | struct work_struct restart_work; | 737 | struct work_struct restart_work; |
@@ -746,21 +756,55 @@ struct bcm43xx_private { | |||
746 | #endif | 756 | #endif |
747 | }; | 757 | }; |
748 | 758 | ||
749 | /* bcm43xx_(un)lock() protect struct bcm43xx_private. | 759 | |
750 | * Note that _NO_ MMIO writes are allowed. If you want to | 760 | /* *** THEORY OF LOCKING *** |
751 | * write to the device through MMIO in the critical section, use | 761 | * |
752 | * the *_mmio lock functions. | 762 | * We have two different locks in the bcm43xx driver. |
753 | * MMIO read-access is allowed, though. | 763 | * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private |
754 | */ | 764 | * and the device registers. |
755 | #define bcm43xx_lock(bcm, flags) spin_lock_irqsave(&(bcm)->_lock, flags) | 765 | * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. |
756 | #define bcm43xx_unlock(bcm, flags) spin_unlock_irqrestore(&(bcm)->_lock, flags) | 766 | * |
757 | /* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO. | 767 | * We have three types of helper function pairs to utilize these locks. |
758 | * MMIO write-access to the device is allowed. | 768 | * (Always use the helper functions.) |
759 | * All MMIO writes are flushed on unlock, so it is guaranteed to not | 769 | * 1) bcm43xx_{un}lock_noirq(): |
760 | * interfere with other threads writing MMIO registers. | 770 | * Takes bcm->mutex. Does _not_ protect against IRQ concurrency, |
771 | * so it is almost always unsafe, if device IRQs are enabled. | ||
772 | * So only use this, if device IRQs are masked. | ||
773 | * Locking may sleep. | ||
774 | * You can sleep within the critical section. | ||
775 | * 2) bcm43xx_{un}lock_irqonly(): | ||
776 | * Takes bcm->irq_lock. Does _not_ protect against | ||
777 | * bcm43xx_lock_noirq() critical sections. | ||
778 | * Does only protect against the IRQ handler path and other | ||
779 | * irqonly() critical sections. | ||
780 | * Locking does not sleep. | ||
781 | * You must not sleep within the critical section. | ||
782 | * 3) bcm43xx_{un}lock_irqsafe(): | ||
783 | * This is the cummulative lock and takes both, mutex and irq_lock. | ||
784 | * Protects against noirq() and irqonly() critical sections (and | ||
785 | * the IRQ handler path). | ||
786 | * Locking may sleep. | ||
787 | * You must not sleep within the critical section. | ||
761 | */ | 788 | */ |
762 | #define bcm43xx_lock_mmio(bcm, flags) bcm43xx_lock(bcm, flags) | 789 | |
763 | #define bcm43xx_unlock_mmio(bcm, flags) do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0) | 790 | /* Lock type 1 */ |
791 | #define bcm43xx_lock_noirq(bcm) mutex_lock(&(bcm)->mutex) | ||
792 | #define bcm43xx_unlock_noirq(bcm) mutex_unlock(&(bcm)->mutex) | ||
793 | /* Lock type 2 */ | ||
794 | #define bcm43xx_lock_irqonly(bcm, flags) \ | ||
795 | spin_lock_irqsave(&(bcm)->irq_lock, flags) | ||
796 | #define bcm43xx_unlock_irqonly(bcm, flags) \ | ||
797 | spin_unlock_irqrestore(&(bcm)->irq_lock, flags) | ||
798 | /* Lock type 3 */ | ||
799 | #define bcm43xx_lock_irqsafe(bcm, flags) do { \ | ||
800 | bcm43xx_lock_noirq(bcm); \ | ||
801 | bcm43xx_lock_irqonly(bcm, flags); \ | ||
802 | } while (0) | ||
803 | #define bcm43xx_unlock_irqsafe(bcm, flags) do { \ | ||
804 | bcm43xx_unlock_irqonly(bcm, flags); \ | ||
805 | bcm43xx_unlock_noirq(bcm); \ | ||
806 | } while (0) | ||
807 | |||
764 | 808 | ||
765 | static inline | 809 | static inline |
766 | struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) | 810 | struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) |
@@ -843,16 +887,6 @@ struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm) | |||
843 | return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio); | 887 | return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio); |
844 | } | 888 | } |
845 | 889 | ||
846 | /* Are we running in init_board() context? */ | ||
847 | static inline | ||
848 | int bcm43xx_is_initializing(struct bcm43xx_private *bcm) | ||
849 | { | ||
850 | if (bcm->initialized) | ||
851 | return 0; | ||
852 | if (bcm->shutting_down) | ||
853 | return 0; | ||
854 | return 1; | ||
855 | } | ||
856 | 890 | ||
857 | static inline | 891 | static inline |
858 | struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy, | 892 | struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy, |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index 7497fb16076e..ce2e40b29b4f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | |||
@@ -77,8 +77,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, | |||
77 | 77 | ||
78 | down(&big_buffer_sem); | 78 | down(&big_buffer_sem); |
79 | 79 | ||
80 | bcm43xx_lock_mmio(bcm, flags); | 80 | bcm43xx_lock_irqsafe(bcm, flags); |
81 | if (!bcm->initialized) { | 81 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { |
82 | fappend("Board not initialized.\n"); | 82 | fappend("Board not initialized.\n"); |
83 | goto out; | 83 | goto out; |
84 | } | 84 | } |
@@ -121,7 +121,7 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, | |||
121 | fappend("\n"); | 121 | fappend("\n"); |
122 | 122 | ||
123 | out: | 123 | out: |
124 | bcm43xx_unlock_mmio(bcm, flags); | 124 | bcm43xx_unlock_irqsafe(bcm, flags); |
125 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 125 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
126 | up(&big_buffer_sem); | 126 | up(&big_buffer_sem); |
127 | return res; | 127 | return res; |
@@ -159,8 +159,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, | |||
159 | unsigned long flags; | 159 | unsigned long flags; |
160 | 160 | ||
161 | down(&big_buffer_sem); | 161 | down(&big_buffer_sem); |
162 | bcm43xx_lock_mmio(bcm, flags); | 162 | bcm43xx_lock_irqsafe(bcm, flags); |
163 | if (!bcm->initialized) { | 163 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { |
164 | fappend("Board not initialized.\n"); | 164 | fappend("Board not initialized.\n"); |
165 | goto out; | 165 | goto out; |
166 | } | 166 | } |
@@ -169,7 +169,7 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, | |||
169 | fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); | 169 | fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); |
170 | 170 | ||
171 | out: | 171 | out: |
172 | bcm43xx_unlock_mmio(bcm, flags); | 172 | bcm43xx_unlock_irqsafe(bcm, flags); |
173 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 173 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
174 | up(&big_buffer_sem); | 174 | up(&big_buffer_sem); |
175 | return res; | 175 | return res; |
@@ -188,8 +188,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, | |||
188 | u64 tsf; | 188 | u64 tsf; |
189 | 189 | ||
190 | down(&big_buffer_sem); | 190 | down(&big_buffer_sem); |
191 | bcm43xx_lock_mmio(bcm, flags); | 191 | bcm43xx_lock_irqsafe(bcm, flags); |
192 | if (!bcm->initialized) { | 192 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { |
193 | fappend("Board not initialized.\n"); | 193 | fappend("Board not initialized.\n"); |
194 | goto out; | 194 | goto out; |
195 | } | 195 | } |
@@ -199,7 +199,7 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, | |||
199 | (unsigned int)(tsf & 0xFFFFFFFFULL)); | 199 | (unsigned int)(tsf & 0xFFFFFFFFULL)); |
200 | 200 | ||
201 | out: | 201 | out: |
202 | bcm43xx_unlock_mmio(bcm, flags); | 202 | bcm43xx_unlock_irqsafe(bcm, flags); |
203 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 203 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
204 | up(&big_buffer_sem); | 204 | up(&big_buffer_sem); |
205 | return res; | 205 | return res; |
@@ -221,8 +221,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, | |||
221 | res = -EFAULT; | 221 | res = -EFAULT; |
222 | goto out_up; | 222 | goto out_up; |
223 | } | 223 | } |
224 | bcm43xx_lock_mmio(bcm, flags); | 224 | bcm43xx_lock_irqsafe(bcm, flags); |
225 | if (!bcm->initialized) { | 225 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { |
226 | printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); | 226 | printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); |
227 | res = -EFAULT; | 227 | res = -EFAULT; |
228 | goto out_unlock; | 228 | goto out_unlock; |
@@ -233,10 +233,11 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, | |||
233 | goto out_unlock; | 233 | goto out_unlock; |
234 | } | 234 | } |
235 | bcm43xx_tsf_write(bcm, tsf); | 235 | bcm43xx_tsf_write(bcm, tsf); |
236 | mmiowb(); | ||
236 | res = buf_size; | 237 | res = buf_size; |
237 | 238 | ||
238 | out_unlock: | 239 | out_unlock: |
239 | bcm43xx_unlock_mmio(bcm, flags); | 240 | bcm43xx_unlock_irqsafe(bcm, flags); |
240 | out_up: | 241 | out_up: |
241 | up(&big_buffer_sem); | 242 | up(&big_buffer_sem); |
242 | return res; | 243 | return res; |
@@ -257,7 +258,7 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, | |||
257 | int i, cnt, j = 0; | 258 | int i, cnt, j = 0; |
258 | 259 | ||
259 | down(&big_buffer_sem); | 260 | down(&big_buffer_sem); |
260 | bcm43xx_lock(bcm, flags); | 261 | bcm43xx_lock_irqsafe(bcm, flags); |
261 | 262 | ||
262 | fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", | 263 | fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", |
263 | BCM43xx_NR_LOGGED_XMITSTATUS); | 264 | BCM43xx_NR_LOGGED_XMITSTATUS); |
@@ -293,14 +294,14 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, | |||
293 | i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; | 294 | i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; |
294 | } | 295 | } |
295 | 296 | ||
296 | bcm43xx_unlock(bcm, flags); | 297 | bcm43xx_unlock_irqsafe(bcm, flags); |
297 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 298 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
298 | bcm43xx_lock(bcm, flags); | 299 | bcm43xx_lock_irqsafe(bcm, flags); |
299 | if (*ppos == pos) { | 300 | if (*ppos == pos) { |
300 | /* Done. Drop the copied data. */ | 301 | /* Done. Drop the copied data. */ |
301 | e->xmitstatus_printing = 0; | 302 | e->xmitstatus_printing = 0; |
302 | } | 303 | } |
303 | bcm43xx_unlock(bcm, flags); | 304 | bcm43xx_unlock_irqsafe(bcm, flags); |
304 | up(&big_buffer_sem); | 305 | up(&big_buffer_sem); |
305 | return res; | 306 | return res; |
306 | } | 307 | } |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 4b2c02c0b31e..ec80692d638a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c | |||
@@ -51,12 +51,12 @@ static void bcm43xx_led_blink(unsigned long d) | |||
51 | struct bcm43xx_private *bcm = led->bcm; | 51 | struct bcm43xx_private *bcm = led->bcm; |
52 | unsigned long flags; | 52 | unsigned long flags; |
53 | 53 | ||
54 | bcm43xx_lock_mmio(bcm, flags); | 54 | bcm43xx_lock_irqonly(bcm, flags); |
55 | if (led->blink_interval) { | 55 | if (led->blink_interval) { |
56 | bcm43xx_led_changestate(led); | 56 | bcm43xx_led_changestate(led); |
57 | mod_timer(&led->blink_timer, jiffies + led->blink_interval); | 57 | mod_timer(&led->blink_timer, jiffies + led->blink_interval); |
58 | } | 58 | } |
59 | bcm43xx_unlock_mmio(bcm, flags); | 59 | bcm43xx_unlock_irqonly(bcm, flags); |
60 | } | 60 | } |
61 | 61 | ||
62 | static void bcm43xx_led_blink_start(struct bcm43xx_led *led, | 62 | static void bcm43xx_led_blink_start(struct bcm43xx_led *led, |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 736dde96c4a3..085d7857fe31 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c | |||
@@ -498,20 +498,31 @@ static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mas | |||
498 | return old_mask; | 498 | return old_mask; |
499 | } | 499 | } |
500 | 500 | ||
501 | /* Synchronize IRQ top- and bottom-half. | ||
502 | * IRQs must be masked before calling this. | ||
503 | * This must not be called with the irq_lock held. | ||
504 | */ | ||
505 | static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm) | ||
506 | { | ||
507 | synchronize_irq(bcm->irq); | ||
508 | tasklet_disable(&bcm->isr_tasklet); | ||
509 | } | ||
510 | |||
501 | /* Make sure we don't receive more data from the device. */ | 511 | /* Make sure we don't receive more data from the device. */ |
502 | static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate) | 512 | static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate) |
503 | { | 513 | { |
504 | u32 old; | ||
505 | unsigned long flags; | 514 | unsigned long flags; |
515 | u32 old; | ||
506 | 516 | ||
507 | bcm43xx_lock_mmio(bcm, flags); | 517 | bcm43xx_lock_irqonly(bcm, flags); |
508 | if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) { | 518 | if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { |
509 | bcm43xx_unlock_mmio(bcm, flags); | 519 | bcm43xx_unlock_irqonly(bcm, flags); |
510 | return -EBUSY; | 520 | return -EBUSY; |
511 | } | 521 | } |
512 | old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | 522 | old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); |
513 | tasklet_disable(&bcm->isr_tasklet); | 523 | bcm43xx_unlock_irqonly(bcm, flags); |
514 | bcm43xx_unlock_mmio(bcm, flags); | 524 | bcm43xx_synchronize_irq(bcm); |
525 | |||
515 | if (oldstate) | 526 | if (oldstate) |
516 | *oldstate = old; | 527 | *oldstate = old; |
517 | 528 | ||
@@ -1389,7 +1400,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) | |||
1389 | bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); | 1400 | bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); |
1390 | #endif | 1401 | #endif |
1391 | } | 1402 | } |
1392 | if (bcm->shutting_down) { | 1403 | if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) { |
1393 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, | 1404 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, |
1394 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) | 1405 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) |
1395 | & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002)); | 1406 | & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002)); |
@@ -1709,7 +1720,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) | |||
1709 | # define bcmirq_handled(irq) do { /* nothing */ } while (0) | 1720 | # define bcmirq_handled(irq) do { /* nothing */ } while (0) |
1710 | #endif /* CONFIG_BCM43XX_DEBUG*/ | 1721 | #endif /* CONFIG_BCM43XX_DEBUG*/ |
1711 | 1722 | ||
1712 | bcm43xx_lock_mmio(bcm, flags); | 1723 | bcm43xx_lock_irqonly(bcm, flags); |
1713 | reason = bcm->irq_reason; | 1724 | reason = bcm->irq_reason; |
1714 | dma_reason[0] = bcm->dma_reason[0]; | 1725 | dma_reason[0] = bcm->dma_reason[0]; |
1715 | dma_reason[1] = bcm->dma_reason[1]; | 1726 | dma_reason[1] = bcm->dma_reason[1]; |
@@ -1734,7 +1745,8 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) | |||
1734 | dma_reason[0], dma_reason[1], | 1745 | dma_reason[0], dma_reason[1], |
1735 | dma_reason[2], dma_reason[3]); | 1746 | dma_reason[2], dma_reason[3]); |
1736 | bcm43xx_controller_restart(bcm, "DMA error"); | 1747 | bcm43xx_controller_restart(bcm, "DMA error"); |
1737 | bcm43xx_unlock_mmio(bcm, flags); | 1748 | mmiowb(); |
1749 | bcm43xx_unlock_irqonly(bcm, flags); | ||
1738 | return; | 1750 | return; |
1739 | } | 1751 | } |
1740 | if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) | | 1752 | if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) | |
@@ -1821,7 +1833,8 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) | |||
1821 | if (!modparam_noleds) | 1833 | if (!modparam_noleds) |
1822 | bcm43xx_leds_update(bcm, activity); | 1834 | bcm43xx_leds_update(bcm, activity); |
1823 | bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); | 1835 | bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); |
1824 | bcm43xx_unlock_mmio(bcm, flags); | 1836 | mmiowb(); |
1837 | bcm43xx_unlock_irqonly(bcm, flags); | ||
1825 | } | 1838 | } |
1826 | 1839 | ||
1827 | static void pio_irq_workaround(struct bcm43xx_private *bcm, | 1840 | static void pio_irq_workaround(struct bcm43xx_private *bcm, |
@@ -1870,7 +1883,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re | |||
1870 | if (!bcm) | 1883 | if (!bcm) |
1871 | return IRQ_NONE; | 1884 | return IRQ_NONE; |
1872 | 1885 | ||
1873 | spin_lock(&bcm->_lock); | 1886 | spin_lock(&bcm->irq_lock); |
1874 | 1887 | ||
1875 | reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); | 1888 | reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); |
1876 | if (reason == 0xffffffff) { | 1889 | if (reason == 0xffffffff) { |
@@ -1899,7 +1912,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re | |||
1899 | * completely, but some careful work is needed to fix this. I think it | 1912 | * completely, but some careful work is needed to fix this. I think it |
1900 | * is best to stay with this cheap workaround for now... . | 1913 | * is best to stay with this cheap workaround for now... . |
1901 | */ | 1914 | */ |
1902 | if (likely(bcm->initialized)) { | 1915 | if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) { |
1903 | /* disable all IRQs. They are enabled again in the bottom half. */ | 1916 | /* disable all IRQs. They are enabled again in the bottom half. */ |
1904 | bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | 1917 | bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); |
1905 | /* save the reason code and call our bottom half. */ | 1918 | /* save the reason code and call our bottom half. */ |
@@ -1909,7 +1922,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re | |||
1909 | 1922 | ||
1910 | out: | 1923 | out: |
1911 | mmiowb(); | 1924 | mmiowb(); |
1912 | spin_unlock(&bcm->_lock); | 1925 | spin_unlock(&bcm->irq_lock); |
1913 | 1926 | ||
1914 | return ret; | 1927 | return ret; |
1915 | } | 1928 | } |
@@ -2133,6 +2146,13 @@ out: | |||
2133 | return err; | 2146 | return err; |
2134 | } | 2147 | } |
2135 | 2148 | ||
2149 | #ifdef CONFIG_BCM947XX | ||
2150 | static struct pci_device_id bcm43xx_47xx_ids[] = { | ||
2151 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) }, | ||
2152 | { 0 } | ||
2153 | }; | ||
2154 | #endif | ||
2155 | |||
2136 | static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) | 2156 | static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) |
2137 | { | 2157 | { |
2138 | int res; | 2158 | int res; |
@@ -2142,11 +2162,15 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) | |||
2142 | bcm->irq = bcm->pci_dev->irq; | 2162 | bcm->irq = bcm->pci_dev->irq; |
2143 | #ifdef CONFIG_BCM947XX | 2163 | #ifdef CONFIG_BCM947XX |
2144 | if (bcm->pci_dev->bus->number == 0) { | 2164 | if (bcm->pci_dev->bus->number == 0) { |
2145 | struct pci_dev *d = NULL; | 2165 | struct pci_dev *d; |
2146 | /* FIXME: we will probably need more device IDs here... */ | 2166 | struct pci_device_id *id; |
2147 | d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL); | 2167 | for (id = bcm43xx_47xx_ids; id->vendor; id++) { |
2148 | if (d != NULL) { | 2168 | d = pci_get_device(id->vendor, id->device, NULL); |
2149 | bcm->irq = d->irq; | 2169 | if (d != NULL) { |
2170 | bcm->irq = d->irq; | ||
2171 | pci_dev_put(d); | ||
2172 | break; | ||
2173 | } | ||
2150 | } | 2174 | } |
2151 | } | 2175 | } |
2152 | #endif | 2176 | #endif |
@@ -3106,15 +3130,10 @@ static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) | |||
3106 | //TODO for APHY (temperature?) | 3130 | //TODO for APHY (temperature?) |
3107 | } | 3131 | } |
3108 | 3132 | ||
3109 | static void bcm43xx_periodic_task_handler(unsigned long d) | 3133 | static void do_periodic_work(struct bcm43xx_private *bcm) |
3110 | { | 3134 | { |
3111 | struct bcm43xx_private *bcm = (struct bcm43xx_private *)d; | ||
3112 | unsigned long flags; | ||
3113 | unsigned int state; | 3135 | unsigned int state; |
3114 | 3136 | ||
3115 | bcm43xx_lock_mmio(bcm, flags); | ||
3116 | |||
3117 | assert(bcm->initialized); | ||
3118 | state = bcm->periodic_state; | 3137 | state = bcm->periodic_state; |
3119 | if (state % 8 == 0) | 3138 | if (state % 8 == 0) |
3120 | bcm43xx_periodic_every120sec(bcm); | 3139 | bcm43xx_periodic_every120sec(bcm); |
@@ -3122,29 +3141,93 @@ static void bcm43xx_periodic_task_handler(unsigned long d) | |||
3122 | bcm43xx_periodic_every60sec(bcm); | 3141 | bcm43xx_periodic_every60sec(bcm); |
3123 | if (state % 2 == 0) | 3142 | if (state % 2 == 0) |
3124 | bcm43xx_periodic_every30sec(bcm); | 3143 | bcm43xx_periodic_every30sec(bcm); |
3125 | bcm43xx_periodic_every15sec(bcm); | 3144 | if (state % 1 == 0) |
3145 | bcm43xx_periodic_every15sec(bcm); | ||
3126 | bcm->periodic_state = state + 1; | 3146 | bcm->periodic_state = state + 1; |
3127 | 3147 | ||
3128 | mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15)); | 3148 | schedule_delayed_work(&bcm->periodic_work, HZ * 15); |
3149 | } | ||
3150 | |||
3151 | /* Estimate a "Badness" value based on the periodic work | ||
3152 | * state-machine state. "Badness" is worse (bigger), if the | ||
3153 | * periodic work will take longer. | ||
3154 | */ | ||
3155 | static int estimate_periodic_work_badness(unsigned int state) | ||
3156 | { | ||
3157 | int badness = 0; | ||
3158 | |||
3159 | if (state % 8 == 0) /* every 120 sec */ | ||
3160 | badness += 10; | ||
3161 | if (state % 4 == 0) /* every 60 sec */ | ||
3162 | badness += 5; | ||
3163 | if (state % 2 == 0) /* every 30 sec */ | ||
3164 | badness += 1; | ||
3165 | if (state % 1 == 0) /* every 15 sec */ | ||
3166 | badness += 1; | ||
3129 | 3167 | ||
3130 | bcm43xx_unlock_mmio(bcm, flags); | 3168 | #define BADNESS_LIMIT 4 |
3169 | return badness; | ||
3170 | } | ||
3171 | |||
3172 | static void bcm43xx_periodic_work_handler(void *d) | ||
3173 | { | ||
3174 | struct bcm43xx_private *bcm = d; | ||
3175 | unsigned long flags; | ||
3176 | u32 savedirqs = 0; | ||
3177 | int badness; | ||
3178 | |||
3179 | badness = estimate_periodic_work_badness(bcm->periodic_state); | ||
3180 | if (badness > BADNESS_LIMIT) { | ||
3181 | /* Periodic work will take a long time, so we want it to | ||
3182 | * be preemtible. | ||
3183 | */ | ||
3184 | bcm43xx_lock_irqonly(bcm, flags); | ||
3185 | netif_stop_queue(bcm->net_dev); | ||
3186 | if (bcm43xx_using_pio(bcm)) | ||
3187 | bcm43xx_pio_freeze_txqueues(bcm); | ||
3188 | savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | ||
3189 | bcm43xx_unlock_irqonly(bcm, flags); | ||
3190 | bcm43xx_lock_noirq(bcm); | ||
3191 | bcm43xx_synchronize_irq(bcm); | ||
3192 | } else { | ||
3193 | /* Periodic work should take short time, so we want low | ||
3194 | * locking overhead. | ||
3195 | */ | ||
3196 | bcm43xx_lock_irqsafe(bcm, flags); | ||
3197 | } | ||
3198 | |||
3199 | do_periodic_work(bcm); | ||
3200 | |||
3201 | if (badness > BADNESS_LIMIT) { | ||
3202 | bcm43xx_lock_irqonly(bcm, flags); | ||
3203 | if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) { | ||
3204 | tasklet_enable(&bcm->isr_tasklet); | ||
3205 | bcm43xx_interrupt_enable(bcm, savedirqs); | ||
3206 | if (bcm43xx_using_pio(bcm)) | ||
3207 | bcm43xx_pio_thaw_txqueues(bcm); | ||
3208 | } | ||
3209 | netif_wake_queue(bcm->net_dev); | ||
3210 | mmiowb(); | ||
3211 | bcm43xx_unlock_irqonly(bcm, flags); | ||
3212 | bcm43xx_unlock_noirq(bcm); | ||
3213 | } else { | ||
3214 | mmiowb(); | ||
3215 | bcm43xx_unlock_irqsafe(bcm, flags); | ||
3216 | } | ||
3131 | } | 3217 | } |
3132 | 3218 | ||
3133 | static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) | 3219 | static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) |
3134 | { | 3220 | { |
3135 | del_timer_sync(&bcm->periodic_tasks); | 3221 | cancel_rearming_delayed_work(&bcm->periodic_work); |
3136 | } | 3222 | } |
3137 | 3223 | ||
3138 | static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) | 3224 | static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) |
3139 | { | 3225 | { |
3140 | struct timer_list *timer = &(bcm->periodic_tasks); | 3226 | struct work_struct *work = &(bcm->periodic_work); |
3141 | 3227 | ||
3142 | assert(bcm->initialized); | 3228 | assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); |
3143 | setup_timer(timer, | 3229 | INIT_WORK(work, bcm43xx_periodic_work_handler, bcm); |
3144 | bcm43xx_periodic_task_handler, | 3230 | schedule_work(work); |
3145 | (unsigned long)bcm); | ||
3146 | timer->expires = jiffies; | ||
3147 | add_timer(timer); | ||
3148 | } | 3231 | } |
3149 | 3232 | ||
3150 | static void bcm43xx_security_init(struct bcm43xx_private *bcm) | 3233 | static void bcm43xx_security_init(struct bcm43xx_private *bcm) |
@@ -3158,16 +3241,12 @@ static void bcm43xx_security_init(struct bcm43xx_private *bcm) | |||
3158 | static void bcm43xx_free_board(struct bcm43xx_private *bcm) | 3241 | static void bcm43xx_free_board(struct bcm43xx_private *bcm) |
3159 | { | 3242 | { |
3160 | int i, err; | 3243 | int i, err; |
3161 | unsigned long flags; | ||
3162 | 3244 | ||
3245 | bcm43xx_lock_noirq(bcm); | ||
3163 | bcm43xx_sysfs_unregister(bcm); | 3246 | bcm43xx_sysfs_unregister(bcm); |
3164 | |||
3165 | bcm43xx_periodic_tasks_delete(bcm); | 3247 | bcm43xx_periodic_tasks_delete(bcm); |
3166 | 3248 | ||
3167 | bcm43xx_lock(bcm, flags); | 3249 | bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); |
3168 | bcm->initialized = 0; | ||
3169 | bcm->shutting_down = 1; | ||
3170 | bcm43xx_unlock(bcm, flags); | ||
3171 | 3250 | ||
3172 | for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { | 3251 | for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { |
3173 | if (!bcm->core_80211[i].available) | 3252 | if (!bcm->core_80211[i].available) |
@@ -3182,23 +3261,19 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) | |||
3182 | 3261 | ||
3183 | bcm43xx_pctl_set_crystal(bcm, 0); | 3262 | bcm43xx_pctl_set_crystal(bcm, 0); |
3184 | 3263 | ||
3185 | bcm43xx_lock(bcm, flags); | 3264 | bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); |
3186 | bcm->shutting_down = 0; | 3265 | bcm43xx_unlock_noirq(bcm); |
3187 | bcm43xx_unlock(bcm, flags); | ||
3188 | } | 3266 | } |
3189 | 3267 | ||
3190 | static int bcm43xx_init_board(struct bcm43xx_private *bcm) | 3268 | static int bcm43xx_init_board(struct bcm43xx_private *bcm) |
3191 | { | 3269 | { |
3192 | int i, err; | 3270 | int i, err; |
3193 | int connect_phy; | 3271 | int connect_phy; |
3194 | unsigned long flags; | ||
3195 | 3272 | ||
3196 | might_sleep(); | 3273 | might_sleep(); |
3197 | 3274 | ||
3198 | bcm43xx_lock(bcm, flags); | 3275 | bcm43xx_lock_noirq(bcm); |
3199 | bcm->initialized = 0; | 3276 | bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); |
3200 | bcm->shutting_down = 0; | ||
3201 | bcm43xx_unlock(bcm, flags); | ||
3202 | 3277 | ||
3203 | err = bcm43xx_pctl_set_crystal(bcm, 1); | 3278 | err = bcm43xx_pctl_set_crystal(bcm, 1); |
3204 | if (err) | 3279 | if (err) |
@@ -3265,9 +3340,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) | |||
3265 | } | 3340 | } |
3266 | 3341 | ||
3267 | /* Initialization of the board is done. Flag it as such. */ | 3342 | /* Initialization of the board is done. Flag it as such. */ |
3268 | bcm43xx_lock(bcm, flags); | 3343 | bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); |
3269 | bcm->initialized = 1; | ||
3270 | bcm43xx_unlock(bcm, flags); | ||
3271 | 3344 | ||
3272 | bcm43xx_periodic_tasks_setup(bcm); | 3345 | bcm43xx_periodic_tasks_setup(bcm); |
3273 | bcm43xx_sysfs_register(bcm); | 3346 | bcm43xx_sysfs_register(bcm); |
@@ -3278,6 +3351,8 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) | |||
3278 | 3351 | ||
3279 | assert(err == 0); | 3352 | assert(err == 0); |
3280 | out: | 3353 | out: |
3354 | bcm43xx_unlock_noirq(bcm); | ||
3355 | |||
3281 | return err; | 3356 | return err; |
3282 | 3357 | ||
3283 | err_80211_unwind: | 3358 | err_80211_unwind: |
@@ -3534,8 +3609,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, | |||
3534 | struct bcm43xx_radioinfo *radio; | 3609 | struct bcm43xx_radioinfo *radio; |
3535 | unsigned long flags; | 3610 | unsigned long flags; |
3536 | 3611 | ||
3537 | bcm43xx_lock_mmio(bcm, flags); | 3612 | bcm43xx_lock_irqsafe(bcm, flags); |
3538 | if (bcm->initialized) { | 3613 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { |
3539 | bcm43xx_mac_suspend(bcm); | 3614 | bcm43xx_mac_suspend(bcm); |
3540 | bcm43xx_radio_selectchannel(bcm, channel, 0); | 3615 | bcm43xx_radio_selectchannel(bcm, channel, 0); |
3541 | bcm43xx_mac_enable(bcm); | 3616 | bcm43xx_mac_enable(bcm); |
@@ -3543,7 +3618,7 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, | |||
3543 | radio = bcm43xx_current_radio(bcm); | 3618 | radio = bcm43xx_current_radio(bcm); |
3544 | radio->initial_channel = channel; | 3619 | radio->initial_channel = channel; |
3545 | } | 3620 | } |
3546 | bcm43xx_unlock_mmio(bcm, flags); | 3621 | bcm43xx_unlock_irqsafe(bcm, flags); |
3547 | } | 3622 | } |
3548 | 3623 | ||
3549 | /* set_security() callback in struct ieee80211_device */ | 3624 | /* set_security() callback in struct ieee80211_device */ |
@@ -3557,7 +3632,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, | |||
3557 | 3632 | ||
3558 | dprintk(KERN_INFO PFX "set security called"); | 3633 | dprintk(KERN_INFO PFX "set security called"); |
3559 | 3634 | ||
3560 | bcm43xx_lock_mmio(bcm, flags); | 3635 | bcm43xx_lock_irqsafe(bcm, flags); |
3561 | 3636 | ||
3562 | for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) | 3637 | for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) |
3563 | if (sec->flags & (1<<keyidx)) { | 3638 | if (sec->flags & (1<<keyidx)) { |
@@ -3587,7 +3662,8 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, | |||
3587 | dprintk(", .encrypt = %d", sec->encrypt); | 3662 | dprintk(", .encrypt = %d", sec->encrypt); |
3588 | } | 3663 | } |
3589 | dprintk("\n"); | 3664 | dprintk("\n"); |
3590 | if (bcm->initialized && !bcm->ieee->host_encrypt) { | 3665 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED && |
3666 | !bcm->ieee->host_encrypt) { | ||
3591 | if (secinfo->enabled) { | 3667 | if (secinfo->enabled) { |
3592 | /* upload WEP keys to hardware */ | 3668 | /* upload WEP keys to hardware */ |
3593 | char null_address[6] = { 0 }; | 3669 | char null_address[6] = { 0 }; |
@@ -3621,7 +3697,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, | |||
3621 | } else | 3697 | } else |
3622 | bcm43xx_clear_keys(bcm); | 3698 | bcm43xx_clear_keys(bcm); |
3623 | } | 3699 | } |
3624 | bcm43xx_unlock_mmio(bcm, flags); | 3700 | bcm43xx_unlock_irqsafe(bcm, flags); |
3625 | } | 3701 | } |
3626 | 3702 | ||
3627 | /* hard_start_xmit() callback in struct ieee80211_device */ | 3703 | /* hard_start_xmit() callback in struct ieee80211_device */ |
@@ -3633,10 +3709,10 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, | |||
3633 | int err = -ENODEV; | 3709 | int err = -ENODEV; |
3634 | unsigned long flags; | 3710 | unsigned long flags; |
3635 | 3711 | ||
3636 | bcm43xx_lock_mmio(bcm, flags); | 3712 | bcm43xx_lock_irqonly(bcm, flags); |
3637 | if (likely(bcm->initialized)) | 3713 | if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) |
3638 | err = bcm43xx_tx(bcm, txb); | 3714 | err = bcm43xx_tx(bcm, txb); |
3639 | bcm43xx_unlock_mmio(bcm, flags); | 3715 | bcm43xx_unlock_irqonly(bcm, flags); |
3640 | 3716 | ||
3641 | return err; | 3717 | return err; |
3642 | } | 3718 | } |
@@ -3651,9 +3727,9 @@ static void bcm43xx_net_tx_timeout(struct net_device *net_dev) | |||
3651 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 3727 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
3652 | unsigned long flags; | 3728 | unsigned long flags; |
3653 | 3729 | ||
3654 | bcm43xx_lock_mmio(bcm, flags); | 3730 | bcm43xx_lock_irqonly(bcm, flags); |
3655 | bcm43xx_controller_restart(bcm, "TX timeout"); | 3731 | bcm43xx_controller_restart(bcm, "TX timeout"); |
3656 | bcm43xx_unlock_mmio(bcm, flags); | 3732 | bcm43xx_unlock_irqonly(bcm, flags); |
3657 | } | 3733 | } |
3658 | 3734 | ||
3659 | #ifdef CONFIG_NET_POLL_CONTROLLER | 3735 | #ifdef CONFIG_NET_POLL_CONTROLLER |
@@ -3678,9 +3754,11 @@ static int bcm43xx_net_open(struct net_device *net_dev) | |||
3678 | static int bcm43xx_net_stop(struct net_device *net_dev) | 3754 | static int bcm43xx_net_stop(struct net_device *net_dev) |
3679 | { | 3755 | { |
3680 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 3756 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
3757 | int err; | ||
3681 | 3758 | ||
3682 | ieee80211softmac_stop(net_dev); | 3759 | ieee80211softmac_stop(net_dev); |
3683 | bcm43xx_disable_interrupts_sync(bcm, NULL); | 3760 | err = bcm43xx_disable_interrupts_sync(bcm, NULL); |
3761 | assert(!err); | ||
3684 | bcm43xx_free_board(bcm); | 3762 | bcm43xx_free_board(bcm); |
3685 | 3763 | ||
3686 | return 0; | 3764 | return 0; |
@@ -3692,6 +3770,7 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, | |||
3692 | { | 3770 | { |
3693 | int err; | 3771 | int err; |
3694 | 3772 | ||
3773 | bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); | ||
3695 | bcm->ieee = netdev_priv(net_dev); | 3774 | bcm->ieee = netdev_priv(net_dev); |
3696 | bcm->softmac = ieee80211_priv(net_dev); | 3775 | bcm->softmac = ieee80211_priv(net_dev); |
3697 | bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; | 3776 | bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; |
@@ -3700,7 +3779,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, | |||
3700 | bcm->pci_dev = pci_dev; | 3779 | bcm->pci_dev = pci_dev; |
3701 | bcm->net_dev = net_dev; | 3780 | bcm->net_dev = net_dev; |
3702 | bcm->bad_frames_preempt = modparam_bad_frames_preempt; | 3781 | bcm->bad_frames_preempt = modparam_bad_frames_preempt; |
3703 | spin_lock_init(&bcm->_lock); | 3782 | spin_lock_init(&bcm->irq_lock); |
3783 | mutex_init(&bcm->mutex); | ||
3704 | tasklet_init(&bcm->isr_tasklet, | 3784 | tasklet_init(&bcm->isr_tasklet, |
3705 | (void (*)(unsigned long))bcm43xx_interrupt_tasklet, | 3785 | (void (*)(unsigned long))bcm43xx_interrupt_tasklet, |
3706 | (unsigned long)bcm); | 3786 | (unsigned long)bcm); |
@@ -3831,7 +3911,7 @@ static void bcm43xx_chip_reset(void *_bcm) | |||
3831 | struct net_device *net_dev = bcm->net_dev; | 3911 | struct net_device *net_dev = bcm->net_dev; |
3832 | struct pci_dev *pci_dev = bcm->pci_dev; | 3912 | struct pci_dev *pci_dev = bcm->pci_dev; |
3833 | int err; | 3913 | int err; |
3834 | int was_initialized = bcm->initialized; | 3914 | int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); |
3835 | 3915 | ||
3836 | netif_stop_queue(bcm->net_dev); | 3916 | netif_stop_queue(bcm->net_dev); |
3837 | tasklet_disable(&bcm->isr_tasklet); | 3917 | tasklet_disable(&bcm->isr_tasklet); |
@@ -3866,6 +3946,7 @@ failure: | |||
3866 | */ | 3946 | */ |
3867 | void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) | 3947 | void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) |
3868 | { | 3948 | { |
3949 | bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING); | ||
3869 | bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | 3950 | bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); |
3870 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ | 3951 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ |
3871 | printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); | 3952 | printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); |
@@ -3884,11 +3965,11 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3884 | 3965 | ||
3885 | dprintk(KERN_INFO PFX "Suspending...\n"); | 3966 | dprintk(KERN_INFO PFX "Suspending...\n"); |
3886 | 3967 | ||
3887 | bcm43xx_lock(bcm, flags); | 3968 | bcm43xx_lock_irqsafe(bcm, flags); |
3888 | bcm->was_initialized = bcm->initialized; | 3969 | bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); |
3889 | if (bcm->initialized) | 3970 | if (bcm->was_initialized) |
3890 | try_to_shutdown = 1; | 3971 | try_to_shutdown = 1; |
3891 | bcm43xx_unlock(bcm, flags); | 3972 | bcm43xx_unlock_irqsafe(bcm, flags); |
3892 | 3973 | ||
3893 | netif_device_detach(net_dev); | 3974 | netif_device_detach(net_dev); |
3894 | if (try_to_shutdown) { | 3975 | if (try_to_shutdown) { |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index b0abac515530..f8200deecc8a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c | |||
@@ -1410,7 +1410,10 @@ static inline | |||
1410 | u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) | 1410 | u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) |
1411 | { | 1411 | { |
1412 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); | 1412 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); |
1413 | u16 ret; | ||
1414 | unsigned long flags; | ||
1413 | 1415 | ||
1416 | local_irq_save(flags); | ||
1414 | if (phy->connected) { | 1417 | if (phy->connected) { |
1415 | bcm43xx_phy_write(bcm, 0x15, 0xE300); | 1418 | bcm43xx_phy_write(bcm, 0x15, 0xE300); |
1416 | control <<= 8; | 1419 | control <<= 8; |
@@ -1430,8 +1433,10 @@ u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) | |||
1430 | bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0); | 1433 | bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0); |
1431 | udelay(8); | 1434 | udelay(8); |
1432 | } | 1435 | } |
1436 | ret = bcm43xx_phy_read(bcm, 0x002D); | ||
1437 | local_irq_restore(flags); | ||
1433 | 1438 | ||
1434 | return bcm43xx_phy_read(bcm, 0x002D); | 1439 | return ret; |
1435 | } | 1440 | } |
1436 | 1441 | ||
1437 | static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control) | 1442 | static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control) |
@@ -1648,7 +1653,7 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, | |||
1648 | void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) | 1653 | void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) |
1649 | { | 1654 | { |
1650 | static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 }; | 1655 | static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 }; |
1651 | const int is_initializing = bcm43xx_is_initializing(bcm); | 1656 | const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING); |
1652 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); | 1657 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); |
1653 | struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); | 1658 | struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); |
1654 | u16 h, i, oldi = 0, j; | 1659 | u16 h, i, oldi = 0, j; |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 0aa1bd269a25..574085c46152 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c | |||
@@ -262,8 +262,10 @@ static void tx_tasklet(unsigned long d) | |||
262 | int err; | 262 | int err; |
263 | u16 txctl; | 263 | u16 txctl; |
264 | 264 | ||
265 | bcm43xx_lock_mmio(bcm, flags); | 265 | bcm43xx_lock_irqonly(bcm, flags); |
266 | 266 | ||
267 | if (queue->tx_frozen) | ||
268 | goto out_unlock; | ||
267 | txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); | 269 | txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); |
268 | if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) | 270 | if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) |
269 | goto out_unlock; | 271 | goto out_unlock; |
@@ -298,7 +300,7 @@ static void tx_tasklet(unsigned long d) | |||
298 | continue; | 300 | continue; |
299 | } | 301 | } |
300 | out_unlock: | 302 | out_unlock: |
301 | bcm43xx_unlock_mmio(bcm, flags); | 303 | bcm43xx_unlock_irqonly(bcm, flags); |
302 | } | 304 | } |
303 | 305 | ||
304 | static void setup_txqueues(struct bcm43xx_pioqueue *queue) | 306 | static void setup_txqueues(struct bcm43xx_pioqueue *queue) |
@@ -374,7 +376,6 @@ static void cancel_transfers(struct bcm43xx_pioqueue *queue) | |||
374 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; | 376 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; |
375 | 377 | ||
376 | netif_tx_disable(queue->bcm->net_dev); | 378 | netif_tx_disable(queue->bcm->net_dev); |
377 | assert(queue->bcm->shutting_down); | ||
378 | tasklet_disable(&queue->txtask); | 379 | tasklet_disable(&queue->txtask); |
379 | 380 | ||
380 | list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) | 381 | list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) |
@@ -634,5 +635,40 @@ void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | |||
634 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) | 635 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) |
635 | & ~BCM43xx_PIO_TXCTL_SUSPEND); | 636 | & ~BCM43xx_PIO_TXCTL_SUSPEND); |
636 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1); | 637 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1); |
637 | tasklet_schedule(&queue->txtask); | 638 | if (!list_empty(&queue->txqueue)) |
639 | tasklet_schedule(&queue->txtask); | ||
640 | } | ||
641 | |||
642 | void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm) | ||
643 | { | ||
644 | struct bcm43xx_pio *pio; | ||
645 | |||
646 | assert(bcm43xx_using_pio(bcm)); | ||
647 | pio = bcm43xx_current_pio(bcm); | ||
648 | pio->queue0->tx_frozen = 1; | ||
649 | pio->queue1->tx_frozen = 1; | ||
650 | pio->queue2->tx_frozen = 1; | ||
651 | pio->queue3->tx_frozen = 1; | ||
638 | } | 652 | } |
653 | |||
654 | void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm) | ||
655 | { | ||
656 | struct bcm43xx_pio *pio; | ||
657 | |||
658 | assert(bcm43xx_using_pio(bcm)); | ||
659 | pio = bcm43xx_current_pio(bcm); | ||
660 | pio->queue0->tx_frozen = 0; | ||
661 | pio->queue1->tx_frozen = 0; | ||
662 | pio->queue2->tx_frozen = 0; | ||
663 | pio->queue3->tx_frozen = 0; | ||
664 | if (!list_empty(&pio->queue0->txqueue)) | ||
665 | tasklet_schedule(&pio->queue0->txtask); | ||
666 | if (!list_empty(&pio->queue1->txqueue)) | ||
667 | tasklet_schedule(&pio->queue1->txtask); | ||
668 | if (!list_empty(&pio->queue2->txqueue)) | ||
669 | tasklet_schedule(&pio->queue2->txtask); | ||
670 | if (!list_empty(&pio->queue3->txqueue)) | ||
671 | tasklet_schedule(&pio->queue3->txtask); | ||
672 | } | ||
673 | |||
674 | |||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h index dfc78209e3a3..bc78a3c2cafb 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h | |||
@@ -54,6 +54,7 @@ struct bcm43xx_pioqueue { | |||
54 | u16 mmio_base; | 54 | u16 mmio_base; |
55 | 55 | ||
56 | u8 tx_suspended:1, | 56 | u8 tx_suspended:1, |
57 | tx_frozen:1, | ||
57 | need_workarounds:1; /* Workarounds needed for core.rev < 3 */ | 58 | need_workarounds:1; /* Workarounds needed for core.rev < 3 */ |
58 | 59 | ||
59 | /* Adjusted size of the device internal TX buffer. */ | 60 | /* Adjusted size of the device internal TX buffer. */ |
@@ -108,8 +109,12 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
108 | struct bcm43xx_xmitstatus *status); | 109 | struct bcm43xx_xmitstatus *status); |
109 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); | 110 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); |
110 | 111 | ||
112 | /* Suspend a TX queue on hardware level. */ | ||
111 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue); | 113 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue); |
112 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue); | 114 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue); |
115 | /* Suspend (freeze) the TX tasklet (software level). */ | ||
116 | void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm); | ||
117 | void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm); | ||
113 | 118 | ||
114 | #else /* CONFIG_BCM43XX_PIO */ | 119 | #else /* CONFIG_BCM43XX_PIO */ |
115 | 120 | ||
@@ -145,6 +150,14 @@ static inline | |||
145 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | 150 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) |
146 | { | 151 | { |
147 | } | 152 | } |
153 | static inline | ||
154 | void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm) | ||
155 | { | ||
156 | } | ||
157 | static inline | ||
158 | void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm) | ||
159 | { | ||
160 | } | ||
148 | 161 | ||
149 | #endif /* CONFIG_BCM43XX_PIO */ | 162 | #endif /* CONFIG_BCM43XX_PIO */ |
150 | #endif /* BCM43xx_PIO_H_ */ | 163 | #endif /* BCM43xx_PIO_H_ */ |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index b438f48e891d..6a23bdc75412 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | |||
@@ -120,12 +120,12 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev, | |||
120 | GFP_KERNEL); | 120 | GFP_KERNEL); |
121 | if (!sprom) | 121 | if (!sprom) |
122 | return -ENOMEM; | 122 | return -ENOMEM; |
123 | bcm43xx_lock_mmio(bcm, flags); | 123 | bcm43xx_lock_irqsafe(bcm, flags); |
124 | assert(bcm->initialized); | ||
125 | err = bcm43xx_sprom_read(bcm, sprom); | 124 | err = bcm43xx_sprom_read(bcm, sprom); |
126 | if (!err) | 125 | if (!err) |
127 | err = sprom2hex(sprom, buf, PAGE_SIZE); | 126 | err = sprom2hex(sprom, buf, PAGE_SIZE); |
128 | bcm43xx_unlock_mmio(bcm, flags); | 127 | mmiowb(); |
128 | bcm43xx_unlock_irqsafe(bcm, flags); | ||
129 | kfree(sprom); | 129 | kfree(sprom); |
130 | 130 | ||
131 | return err; | 131 | return err; |
@@ -150,10 +150,10 @@ static ssize_t bcm43xx_attr_sprom_store(struct device *dev, | |||
150 | err = hex2sprom(sprom, buf, count); | 150 | err = hex2sprom(sprom, buf, count); |
151 | if (err) | 151 | if (err) |
152 | goto out_kfree; | 152 | goto out_kfree; |
153 | bcm43xx_lock_mmio(bcm, flags); | 153 | bcm43xx_lock_irqsafe(bcm, flags); |
154 | assert(bcm->initialized); | ||
155 | err = bcm43xx_sprom_write(bcm, sprom); | 154 | err = bcm43xx_sprom_write(bcm, sprom); |
156 | bcm43xx_unlock_mmio(bcm, flags); | 155 | mmiowb(); |
156 | bcm43xx_unlock_irqsafe(bcm, flags); | ||
157 | out_kfree: | 157 | out_kfree: |
158 | kfree(sprom); | 158 | kfree(sprom); |
159 | 159 | ||
@@ -170,15 +170,13 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, | |||
170 | char *buf) | 170 | char *buf) |
171 | { | 171 | { |
172 | struct bcm43xx_private *bcm = dev_to_bcm(dev); | 172 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
173 | unsigned long flags; | ||
174 | int err; | 173 | int err; |
175 | ssize_t count = 0; | 174 | ssize_t count = 0; |
176 | 175 | ||
177 | if (!capable(CAP_NET_ADMIN)) | 176 | if (!capable(CAP_NET_ADMIN)) |
178 | return -EPERM; | 177 | return -EPERM; |
179 | 178 | ||
180 | bcm43xx_lock(bcm, flags); | 179 | bcm43xx_lock_noirq(bcm); |
181 | assert(bcm->initialized); | ||
182 | 180 | ||
183 | switch (bcm43xx_current_radio(bcm)->interfmode) { | 181 | switch (bcm43xx_current_radio(bcm)->interfmode) { |
184 | case BCM43xx_RADIO_INTERFMODE_NONE: | 182 | case BCM43xx_RADIO_INTERFMODE_NONE: |
@@ -195,7 +193,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, | |||
195 | } | 193 | } |
196 | err = 0; | 194 | err = 0; |
197 | 195 | ||
198 | bcm43xx_unlock(bcm, flags); | 196 | bcm43xx_unlock_noirq(bcm); |
199 | 197 | ||
200 | return err ? err : count; | 198 | return err ? err : count; |
201 | 199 | ||
@@ -231,16 +229,15 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, | |||
231 | return -EINVAL; | 229 | return -EINVAL; |
232 | } | 230 | } |
233 | 231 | ||
234 | bcm43xx_lock_mmio(bcm, flags); | 232 | bcm43xx_lock_irqsafe(bcm, flags); |
235 | assert(bcm->initialized); | ||
236 | 233 | ||
237 | err = bcm43xx_radio_set_interference_mitigation(bcm, mode); | 234 | err = bcm43xx_radio_set_interference_mitigation(bcm, mode); |
238 | if (err) { | 235 | if (err) { |
239 | printk(KERN_ERR PFX "Interference Mitigation not " | 236 | printk(KERN_ERR PFX "Interference Mitigation not " |
240 | "supported by device\n"); | 237 | "supported by device\n"); |
241 | } | 238 | } |
242 | 239 | mmiowb(); | |
243 | bcm43xx_unlock_mmio(bcm, flags); | 240 | bcm43xx_unlock_irqsafe(bcm, flags); |
244 | 241 | ||
245 | return err ? err : count; | 242 | return err ? err : count; |
246 | } | 243 | } |
@@ -254,15 +251,13 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, | |||
254 | char *buf) | 251 | char *buf) |
255 | { | 252 | { |
256 | struct bcm43xx_private *bcm = dev_to_bcm(dev); | 253 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
257 | unsigned long flags; | ||
258 | int err; | 254 | int err; |
259 | ssize_t count; | 255 | ssize_t count; |
260 | 256 | ||
261 | if (!capable(CAP_NET_ADMIN)) | 257 | if (!capable(CAP_NET_ADMIN)) |
262 | return -EPERM; | 258 | return -EPERM; |
263 | 259 | ||
264 | bcm43xx_lock(bcm, flags); | 260 | bcm43xx_lock_noirq(bcm); |
265 | assert(bcm->initialized); | ||
266 | 261 | ||
267 | if (bcm->short_preamble) | 262 | if (bcm->short_preamble) |
268 | count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); | 263 | count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); |
@@ -270,7 +265,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, | |||
270 | count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); | 265 | count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); |
271 | 266 | ||
272 | err = 0; | 267 | err = 0; |
273 | bcm43xx_unlock(bcm, flags); | 268 | bcm43xx_unlock_noirq(bcm); |
274 | 269 | ||
275 | return err ? err : count; | 270 | return err ? err : count; |
276 | } | 271 | } |
@@ -290,13 +285,12 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, | |||
290 | value = get_boolean(buf, count); | 285 | value = get_boolean(buf, count); |
291 | if (value < 0) | 286 | if (value < 0) |
292 | return value; | 287 | return value; |
293 | bcm43xx_lock(bcm, flags); | 288 | bcm43xx_lock_irqsafe(bcm, flags); |
294 | assert(bcm->initialized); | ||
295 | 289 | ||
296 | bcm->short_preamble = !!value; | 290 | bcm->short_preamble = !!value; |
297 | 291 | ||
298 | err = 0; | 292 | err = 0; |
299 | bcm43xx_unlock(bcm, flags); | 293 | bcm43xx_unlock_irqsafe(bcm, flags); |
300 | 294 | ||
301 | return err ? err : count; | 295 | return err ? err : count; |
302 | } | 296 | } |
@@ -310,7 +304,7 @@ int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) | |||
310 | struct device *dev = &bcm->pci_dev->dev; | 304 | struct device *dev = &bcm->pci_dev->dev; |
311 | int err; | 305 | int err; |
312 | 306 | ||
313 | assert(bcm->initialized); | 307 | assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); |
314 | 308 | ||
315 | err = device_create_file(dev, &dev_attr_sprom); | 309 | err = device_create_file(dev, &dev_attr_sprom); |
316 | if (err) | 310 | if (err) |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index b45063974ae9..c35cb3a0777e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c | |||
@@ -55,13 +55,13 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, | |||
55 | char *extra) | 55 | char *extra) |
56 | { | 56 | { |
57 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 57 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
58 | unsigned long flags; | ||
59 | int i; | 58 | int i; |
59 | unsigned long flags; | ||
60 | struct bcm43xx_phyinfo *phy; | 60 | struct bcm43xx_phyinfo *phy; |
61 | char suffix[7] = { 0 }; | 61 | char suffix[7] = { 0 }; |
62 | int have_a = 0, have_b = 0, have_g = 0; | 62 | int have_a = 0, have_b = 0, have_g = 0; |
63 | 63 | ||
64 | bcm43xx_lock(bcm, flags); | 64 | bcm43xx_lock_irqsafe(bcm, flags); |
65 | for (i = 0; i < bcm->nr_80211_available; i++) { | 65 | for (i = 0; i < bcm->nr_80211_available; i++) { |
66 | phy = &(bcm->core_80211_ext[i].phy); | 66 | phy = &(bcm->core_80211_ext[i].phy); |
67 | switch (phy->type) { | 67 | switch (phy->type) { |
@@ -77,7 +77,7 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, | |||
77 | assert(0); | 77 | assert(0); |
78 | } | 78 | } |
79 | } | 79 | } |
80 | bcm43xx_unlock(bcm, flags); | 80 | bcm43xx_unlock_irqsafe(bcm, flags); |
81 | 81 | ||
82 | i = 0; | 82 | i = 0; |
83 | if (have_a) { | 83 | if (have_a) { |
@@ -111,7 +111,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, | |||
111 | int freq; | 111 | int freq; |
112 | int err = -EINVAL; | 112 | int err = -EINVAL; |
113 | 113 | ||
114 | bcm43xx_lock_mmio(bcm, flags); | 114 | bcm43xx_lock_irqsafe(bcm, flags); |
115 | if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { | 115 | if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { |
116 | channel = data->freq.m; | 116 | channel = data->freq.m; |
117 | freq = bcm43xx_channel_to_freq(bcm, channel); | 117 | freq = bcm43xx_channel_to_freq(bcm, channel); |
@@ -121,7 +121,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, | |||
121 | } | 121 | } |
122 | if (!bcm43xx_is_valid_channel(bcm, channel)) | 122 | if (!bcm43xx_is_valid_channel(bcm, channel)) |
123 | goto out_unlock; | 123 | goto out_unlock; |
124 | if (bcm->initialized) { | 124 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { |
125 | //ieee80211softmac_disassoc(softmac, $REASON); | 125 | //ieee80211softmac_disassoc(softmac, $REASON); |
126 | bcm43xx_mac_suspend(bcm); | 126 | bcm43xx_mac_suspend(bcm); |
127 | err = bcm43xx_radio_selectchannel(bcm, channel, 0); | 127 | err = bcm43xx_radio_selectchannel(bcm, channel, 0); |
@@ -131,7 +131,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, | |||
131 | err = 0; | 131 | err = 0; |
132 | } | 132 | } |
133 | out_unlock: | 133 | out_unlock: |
134 | bcm43xx_unlock_mmio(bcm, flags); | 134 | bcm43xx_unlock_irqsafe(bcm, flags); |
135 | 135 | ||
136 | return err; | 136 | return err; |
137 | } | 137 | } |
@@ -147,11 +147,10 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, | |||
147 | int err = -ENODEV; | 147 | int err = -ENODEV; |
148 | u16 channel; | 148 | u16 channel; |
149 | 149 | ||
150 | bcm43xx_lock(bcm, flags); | 150 | bcm43xx_lock_irqsafe(bcm, flags); |
151 | radio = bcm43xx_current_radio(bcm); | 151 | radio = bcm43xx_current_radio(bcm); |
152 | channel = radio->channel; | 152 | channel = radio->channel; |
153 | if (channel == 0xFF) { | 153 | if (channel == 0xFF) { |
154 | assert(!bcm->initialized); | ||
155 | channel = radio->initial_channel; | 154 | channel = radio->initial_channel; |
156 | if (channel == 0xFF) | 155 | if (channel == 0xFF) |
157 | goto out_unlock; | 156 | goto out_unlock; |
@@ -163,7 +162,7 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, | |||
163 | 162 | ||
164 | err = 0; | 163 | err = 0; |
165 | out_unlock: | 164 | out_unlock: |
166 | bcm43xx_unlock(bcm, flags); | 165 | bcm43xx_unlock_irqsafe(bcm, flags); |
167 | 166 | ||
168 | return err; | 167 | return err; |
169 | } | 168 | } |
@@ -181,13 +180,13 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev, | |||
181 | if (mode == IW_MODE_AUTO) | 180 | if (mode == IW_MODE_AUTO) |
182 | mode = BCM43xx_INITIAL_IWMODE; | 181 | mode = BCM43xx_INITIAL_IWMODE; |
183 | 182 | ||
184 | bcm43xx_lock_mmio(bcm, flags); | 183 | bcm43xx_lock_irqsafe(bcm, flags); |
185 | if (bcm->initialized) { | 184 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { |
186 | if (bcm->ieee->iw_mode != mode) | 185 | if (bcm->ieee->iw_mode != mode) |
187 | bcm43xx_set_iwmode(bcm, mode); | 186 | bcm43xx_set_iwmode(bcm, mode); |
188 | } else | 187 | } else |
189 | bcm->ieee->iw_mode = mode; | 188 | bcm->ieee->iw_mode = mode; |
190 | bcm43xx_unlock_mmio(bcm, flags); | 189 | bcm43xx_unlock_irqsafe(bcm, flags); |
191 | 190 | ||
192 | return 0; | 191 | return 0; |
193 | } | 192 | } |
@@ -200,9 +199,9 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev, | |||
200 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 199 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
201 | unsigned long flags; | 200 | unsigned long flags; |
202 | 201 | ||
203 | bcm43xx_lock(bcm, flags); | 202 | bcm43xx_lock_irqsafe(bcm, flags); |
204 | data->mode = bcm->ieee->iw_mode; | 203 | data->mode = bcm->ieee->iw_mode; |
205 | bcm43xx_unlock(bcm, flags); | 204 | bcm43xx_unlock_irqsafe(bcm, flags); |
206 | 205 | ||
207 | return 0; | 206 | return 0; |
208 | } | 207 | } |
@@ -255,7 +254,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, | |||
255 | IW_ENC_CAPA_CIPHER_TKIP | | 254 | IW_ENC_CAPA_CIPHER_TKIP | |
256 | IW_ENC_CAPA_CIPHER_CCMP; | 255 | IW_ENC_CAPA_CIPHER_CCMP; |
257 | 256 | ||
258 | bcm43xx_lock(bcm, flags); | 257 | bcm43xx_lock_irqsafe(bcm, flags); |
259 | phy = bcm43xx_current_phy(bcm); | 258 | phy = bcm43xx_current_phy(bcm); |
260 | 259 | ||
261 | range->num_bitrates = 0; | 260 | range->num_bitrates = 0; |
@@ -302,7 +301,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, | |||
302 | } | 301 | } |
303 | range->num_frequency = j; | 302 | range->num_frequency = j; |
304 | 303 | ||
305 | bcm43xx_unlock(bcm, flags); | 304 | bcm43xx_unlock_irqsafe(bcm, flags); |
306 | 305 | ||
307 | return 0; | 306 | return 0; |
308 | } | 307 | } |
@@ -313,14 +312,13 @@ static int bcm43xx_wx_set_nick(struct net_device *net_dev, | |||
313 | char *extra) | 312 | char *extra) |
314 | { | 313 | { |
315 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 314 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
316 | unsigned long flags; | ||
317 | size_t len; | 315 | size_t len; |
318 | 316 | ||
319 | bcm43xx_lock(bcm, flags); | 317 | bcm43xx_lock_noirq(bcm); |
320 | len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); | 318 | len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); |
321 | memcpy(bcm->nick, extra, len); | 319 | memcpy(bcm->nick, extra, len); |
322 | bcm->nick[len] = '\0'; | 320 | bcm->nick[len] = '\0'; |
323 | bcm43xx_unlock(bcm, flags); | 321 | bcm43xx_unlock_noirq(bcm); |
324 | 322 | ||
325 | return 0; | 323 | return 0; |
326 | } | 324 | } |
@@ -331,15 +329,14 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev, | |||
331 | char *extra) | 329 | char *extra) |
332 | { | 330 | { |
333 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 331 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
334 | unsigned long flags; | ||
335 | size_t len; | 332 | size_t len; |
336 | 333 | ||
337 | bcm43xx_lock(bcm, flags); | 334 | bcm43xx_lock_noirq(bcm); |
338 | len = strlen(bcm->nick) + 1; | 335 | len = strlen(bcm->nick) + 1; |
339 | memcpy(extra, bcm->nick, len); | 336 | memcpy(extra, bcm->nick, len); |
340 | data->data.length = (__u16)len; | 337 | data->data.length = (__u16)len; |
341 | data->data.flags = 1; | 338 | data->data.flags = 1; |
342 | bcm43xx_unlock(bcm, flags); | 339 | bcm43xx_unlock_noirq(bcm); |
343 | 340 | ||
344 | return 0; | 341 | return 0; |
345 | } | 342 | } |
@@ -353,7 +350,7 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, | |||
353 | unsigned long flags; | 350 | unsigned long flags; |
354 | int err = -EINVAL; | 351 | int err = -EINVAL; |
355 | 352 | ||
356 | bcm43xx_lock(bcm, flags); | 353 | bcm43xx_lock_irqsafe(bcm, flags); |
357 | if (data->rts.disabled) { | 354 | if (data->rts.disabled) { |
358 | bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; | 355 | bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; |
359 | err = 0; | 356 | err = 0; |
@@ -364,7 +361,7 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, | |||
364 | err = 0; | 361 | err = 0; |
365 | } | 362 | } |
366 | } | 363 | } |
367 | bcm43xx_unlock(bcm, flags); | 364 | bcm43xx_unlock_irqsafe(bcm, flags); |
368 | 365 | ||
369 | return err; | 366 | return err; |
370 | } | 367 | } |
@@ -377,11 +374,11 @@ static int bcm43xx_wx_get_rts(struct net_device *net_dev, | |||
377 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 374 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
378 | unsigned long flags; | 375 | unsigned long flags; |
379 | 376 | ||
380 | bcm43xx_lock(bcm, flags); | 377 | bcm43xx_lock_irqsafe(bcm, flags); |
381 | data->rts.value = bcm->rts_threshold; | 378 | data->rts.value = bcm->rts_threshold; |
382 | data->rts.fixed = 0; | 379 | data->rts.fixed = 0; |
383 | data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); | 380 | data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); |
384 | bcm43xx_unlock(bcm, flags); | 381 | bcm43xx_unlock_irqsafe(bcm, flags); |
385 | 382 | ||
386 | return 0; | 383 | return 0; |
387 | } | 384 | } |
@@ -395,7 +392,7 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, | |||
395 | unsigned long flags; | 392 | unsigned long flags; |
396 | int err = -EINVAL; | 393 | int err = -EINVAL; |
397 | 394 | ||
398 | bcm43xx_lock(bcm, flags); | 395 | bcm43xx_lock_irqsafe(bcm, flags); |
399 | if (data->frag.disabled) { | 396 | if (data->frag.disabled) { |
400 | bcm->ieee->fts = MAX_FRAG_THRESHOLD; | 397 | bcm->ieee->fts = MAX_FRAG_THRESHOLD; |
401 | err = 0; | 398 | err = 0; |
@@ -406,7 +403,7 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, | |||
406 | err = 0; | 403 | err = 0; |
407 | } | 404 | } |
408 | } | 405 | } |
409 | bcm43xx_unlock(bcm, flags); | 406 | bcm43xx_unlock_irqsafe(bcm, flags); |
410 | 407 | ||
411 | return err; | 408 | return err; |
412 | } | 409 | } |
@@ -419,11 +416,11 @@ static int bcm43xx_wx_get_frag(struct net_device *net_dev, | |||
419 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 416 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
420 | unsigned long flags; | 417 | unsigned long flags; |
421 | 418 | ||
422 | bcm43xx_lock(bcm, flags); | 419 | bcm43xx_lock_irqsafe(bcm, flags); |
423 | data->frag.value = bcm->ieee->fts; | 420 | data->frag.value = bcm->ieee->fts; |
424 | data->frag.fixed = 0; | 421 | data->frag.fixed = 0; |
425 | data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); | 422 | data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); |
426 | bcm43xx_unlock(bcm, flags); | 423 | bcm43xx_unlock_irqsafe(bcm, flags); |
427 | 424 | ||
428 | return 0; | 425 | return 0; |
429 | } | 426 | } |
@@ -445,8 +442,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, | |||
445 | return -EOPNOTSUPP; | 442 | return -EOPNOTSUPP; |
446 | } | 443 | } |
447 | 444 | ||
448 | bcm43xx_lock_mmio(bcm, flags); | 445 | bcm43xx_lock_irqsafe(bcm, flags); |
449 | if (!bcm->initialized) | 446 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) |
450 | goto out_unlock; | 447 | goto out_unlock; |
451 | radio = bcm43xx_current_radio(bcm); | 448 | radio = bcm43xx_current_radio(bcm); |
452 | phy = bcm43xx_current_phy(bcm); | 449 | phy = bcm43xx_current_phy(bcm); |
@@ -469,7 +466,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, | |||
469 | err = 0; | 466 | err = 0; |
470 | 467 | ||
471 | out_unlock: | 468 | out_unlock: |
472 | bcm43xx_unlock_mmio(bcm, flags); | 469 | bcm43xx_unlock_irqsafe(bcm, flags); |
473 | 470 | ||
474 | return err; | 471 | return err; |
475 | } | 472 | } |
@@ -484,8 +481,8 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, | |||
484 | unsigned long flags; | 481 | unsigned long flags; |
485 | int err = -ENODEV; | 482 | int err = -ENODEV; |
486 | 483 | ||
487 | bcm43xx_lock(bcm, flags); | 484 | bcm43xx_lock_irqsafe(bcm, flags); |
488 | if (!bcm->initialized) | 485 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) |
489 | goto out_unlock; | 486 | goto out_unlock; |
490 | radio = bcm43xx_current_radio(bcm); | 487 | radio = bcm43xx_current_radio(bcm); |
491 | /* desired dBm value is in Q5.2 */ | 488 | /* desired dBm value is in Q5.2 */ |
@@ -496,7 +493,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, | |||
496 | 493 | ||
497 | err = 0; | 494 | err = 0; |
498 | out_unlock: | 495 | out_unlock: |
499 | bcm43xx_unlock(bcm, flags); | 496 | bcm43xx_unlock_irqsafe(bcm, flags); |
500 | 497 | ||
501 | return err; | 498 | return err; |
502 | } | 499 | } |
@@ -583,8 +580,8 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, | |||
583 | return -EINVAL; | 580 | return -EINVAL; |
584 | } | 581 | } |
585 | 582 | ||
586 | bcm43xx_lock_mmio(bcm, flags); | 583 | bcm43xx_lock_irqsafe(bcm, flags); |
587 | if (bcm->initialized) { | 584 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { |
588 | err = bcm43xx_radio_set_interference_mitigation(bcm, mode); | 585 | err = bcm43xx_radio_set_interference_mitigation(bcm, mode); |
589 | if (err) { | 586 | if (err) { |
590 | printk(KERN_ERR PFX "Interference Mitigation not " | 587 | printk(KERN_ERR PFX "Interference Mitigation not " |
@@ -598,7 +595,7 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, | |||
598 | } else | 595 | } else |
599 | bcm43xx_current_radio(bcm)->interfmode = mode; | 596 | bcm43xx_current_radio(bcm)->interfmode = mode; |
600 | } | 597 | } |
601 | bcm43xx_unlock_mmio(bcm, flags); | 598 | bcm43xx_unlock_irqsafe(bcm, flags); |
602 | 599 | ||
603 | return err; | 600 | return err; |
604 | } | 601 | } |
@@ -612,9 +609,9 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, | |||
612 | unsigned long flags; | 609 | unsigned long flags; |
613 | int mode; | 610 | int mode; |
614 | 611 | ||
615 | bcm43xx_lock(bcm, flags); | 612 | bcm43xx_lock_irqsafe(bcm, flags); |
616 | mode = bcm43xx_current_radio(bcm)->interfmode; | 613 | mode = bcm43xx_current_radio(bcm)->interfmode; |
617 | bcm43xx_unlock(bcm, flags); | 614 | bcm43xx_unlock_irqsafe(bcm, flags); |
618 | 615 | ||
619 | switch (mode) { | 616 | switch (mode) { |
620 | case BCM43xx_RADIO_INTERFMODE_NONE: | 617 | case BCM43xx_RADIO_INTERFMODE_NONE: |
@@ -644,9 +641,9 @@ static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, | |||
644 | int on; | 641 | int on; |
645 | 642 | ||
646 | on = *((int *)extra); | 643 | on = *((int *)extra); |
647 | bcm43xx_lock(bcm, flags); | 644 | bcm43xx_lock_irqsafe(bcm, flags); |
648 | bcm->short_preamble = !!on; | 645 | bcm->short_preamble = !!on; |
649 | bcm43xx_unlock(bcm, flags); | 646 | bcm43xx_unlock_irqsafe(bcm, flags); |
650 | 647 | ||
651 | return 0; | 648 | return 0; |
652 | } | 649 | } |
@@ -660,9 +657,9 @@ static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, | |||
660 | unsigned long flags; | 657 | unsigned long flags; |
661 | int on; | 658 | int on; |
662 | 659 | ||
663 | bcm43xx_lock(bcm, flags); | 660 | bcm43xx_lock_irqsafe(bcm, flags); |
664 | on = bcm->short_preamble; | 661 | on = bcm->short_preamble; |
665 | bcm43xx_unlock(bcm, flags); | 662 | bcm43xx_unlock_irqsafe(bcm, flags); |
666 | 663 | ||
667 | if (on) | 664 | if (on) |
668 | strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); | 665 | strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); |
@@ -684,11 +681,11 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, | |||
684 | 681 | ||
685 | on = *((int *)extra); | 682 | on = *((int *)extra); |
686 | 683 | ||
687 | bcm43xx_lock(bcm, flags); | 684 | bcm43xx_lock_irqsafe(bcm, flags); |
688 | bcm->ieee->host_encrypt = !!on; | 685 | bcm->ieee->host_encrypt = !!on; |
689 | bcm->ieee->host_decrypt = !!on; | 686 | bcm->ieee->host_decrypt = !!on; |
690 | bcm->ieee->host_build_iv = !on; | 687 | bcm->ieee->host_build_iv = !on; |
691 | bcm43xx_unlock(bcm, flags); | 688 | bcm43xx_unlock_irqsafe(bcm, flags); |
692 | 689 | ||
693 | return 0; | 690 | return 0; |
694 | } | 691 | } |
@@ -702,9 +699,9 @@ static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, | |||
702 | unsigned long flags; | 699 | unsigned long flags; |
703 | int on; | 700 | int on; |
704 | 701 | ||
705 | bcm43xx_lock(bcm, flags); | 702 | bcm43xx_lock_irqsafe(bcm, flags); |
706 | on = bcm->ieee->host_encrypt; | 703 | on = bcm->ieee->host_encrypt; |
707 | bcm43xx_unlock(bcm, flags); | 704 | bcm43xx_unlock_irqsafe(bcm, flags); |
708 | 705 | ||
709 | if (on) | 706 | if (on) |
710 | strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); | 707 | strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); |
@@ -767,11 +764,11 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev, | |||
767 | if (!sprom) | 764 | if (!sprom) |
768 | goto out; | 765 | goto out; |
769 | 766 | ||
770 | bcm43xx_lock_mmio(bcm, flags); | 767 | bcm43xx_lock_irqsafe(bcm, flags); |
771 | err = -ENODEV; | 768 | err = -ENODEV; |
772 | if (bcm->initialized) | 769 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) |
773 | err = bcm43xx_sprom_read(bcm, sprom); | 770 | err = bcm43xx_sprom_read(bcm, sprom); |
774 | bcm43xx_unlock_mmio(bcm, flags); | 771 | bcm43xx_unlock_irqsafe(bcm, flags); |
775 | if (!err) | 772 | if (!err) |
776 | data->data.length = sprom2hex(sprom, extra); | 773 | data->data.length = sprom2hex(sprom, extra); |
777 | kfree(sprom); | 774 | kfree(sprom); |
@@ -812,11 +809,11 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, | |||
812 | if (err) | 809 | if (err) |
813 | goto out_kfree; | 810 | goto out_kfree; |
814 | 811 | ||
815 | bcm43xx_lock_mmio(bcm, flags); | 812 | bcm43xx_lock_irqsafe(bcm, flags); |
816 | err = -ENODEV; | 813 | err = -ENODEV; |
817 | if (bcm->initialized) | 814 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) |
818 | err = bcm43xx_sprom_write(bcm, sprom); | 815 | err = bcm43xx_sprom_write(bcm, sprom); |
819 | bcm43xx_unlock_mmio(bcm, flags); | 816 | bcm43xx_unlock_irqsafe(bcm, flags); |
820 | out_kfree: | 817 | out_kfree: |
821 | kfree(sprom); | 818 | kfree(sprom); |
822 | out: | 819 | out: |
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 39f82f219749..081a8999666e 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
@@ -533,7 +533,7 @@ static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask) | |||
533 | ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask); | 533 | ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask); |
534 | } | 534 | } |
535 | 535 | ||
536 | static inline void ipw_enable_interrupts(struct ipw_priv *priv) | 536 | static inline void __ipw_enable_interrupts(struct ipw_priv *priv) |
537 | { | 537 | { |
538 | if (priv->status & STATUS_INT_ENABLED) | 538 | if (priv->status & STATUS_INT_ENABLED) |
539 | return; | 539 | return; |
@@ -541,7 +541,7 @@ static inline void ipw_enable_interrupts(struct ipw_priv *priv) | |||
541 | ipw_write32(priv, IPW_INTA_MASK_R, IPW_INTA_MASK_ALL); | 541 | ipw_write32(priv, IPW_INTA_MASK_R, IPW_INTA_MASK_ALL); |
542 | } | 542 | } |
543 | 543 | ||
544 | static inline void ipw_disable_interrupts(struct ipw_priv *priv) | 544 | static inline void __ipw_disable_interrupts(struct ipw_priv *priv) |
545 | { | 545 | { |
546 | if (!(priv->status & STATUS_INT_ENABLED)) | 546 | if (!(priv->status & STATUS_INT_ENABLED)) |
547 | return; | 547 | return; |
@@ -549,6 +549,24 @@ static inline void ipw_disable_interrupts(struct ipw_priv *priv) | |||
549 | ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); | 549 | ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); |
550 | } | 550 | } |
551 | 551 | ||
552 | static inline void ipw_enable_interrupts(struct ipw_priv *priv) | ||
553 | { | ||
554 | unsigned long flags; | ||
555 | |||
556 | spin_lock_irqsave(&priv->irq_lock, flags); | ||
557 | __ipw_enable_interrupts(priv); | ||
558 | spin_unlock_irqrestore(&priv->irq_lock, flags); | ||
559 | } | ||
560 | |||
561 | static inline void ipw_disable_interrupts(struct ipw_priv *priv) | ||
562 | { | ||
563 | unsigned long flags; | ||
564 | |||
565 | spin_lock_irqsave(&priv->irq_lock, flags); | ||
566 | __ipw_disable_interrupts(priv); | ||
567 | spin_unlock_irqrestore(&priv->irq_lock, flags); | ||
568 | } | ||
569 | |||
552 | #ifdef CONFIG_IPW2200_DEBUG | 570 | #ifdef CONFIG_IPW2200_DEBUG |
553 | static char *ipw_error_desc(u32 val) | 571 | static char *ipw_error_desc(u32 val) |
554 | { | 572 | { |
@@ -1856,7 +1874,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
1856 | unsigned long flags; | 1874 | unsigned long flags; |
1857 | int rc = 0; | 1875 | int rc = 0; |
1858 | 1876 | ||
1859 | spin_lock_irqsave(&priv->lock, flags); | 1877 | spin_lock_irqsave(&priv->irq_lock, flags); |
1860 | 1878 | ||
1861 | inta = ipw_read32(priv, IPW_INTA_RW); | 1879 | inta = ipw_read32(priv, IPW_INTA_RW); |
1862 | inta_mask = ipw_read32(priv, IPW_INTA_MASK_R); | 1880 | inta_mask = ipw_read32(priv, IPW_INTA_MASK_R); |
@@ -1865,6 +1883,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
1865 | /* Add any cached INTA values that need to be handled */ | 1883 | /* Add any cached INTA values that need to be handled */ |
1866 | inta |= priv->isr_inta; | 1884 | inta |= priv->isr_inta; |
1867 | 1885 | ||
1886 | spin_unlock_irqrestore(&priv->irq_lock, flags); | ||
1887 | |||
1888 | spin_lock_irqsave(&priv->lock, flags); | ||
1889 | |||
1868 | /* handle all the justifications for the interrupt */ | 1890 | /* handle all the justifications for the interrupt */ |
1869 | if (inta & IPW_INTA_BIT_RX_TRANSFER) { | 1891 | if (inta & IPW_INTA_BIT_RX_TRANSFER) { |
1870 | ipw_rx(priv); | 1892 | ipw_rx(priv); |
@@ -1993,10 +2015,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
1993 | IPW_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled); | 2015 | IPW_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled); |
1994 | } | 2016 | } |
1995 | 2017 | ||
2018 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2019 | |||
1996 | /* enable all interrupts */ | 2020 | /* enable all interrupts */ |
1997 | ipw_enable_interrupts(priv); | 2021 | ipw_enable_interrupts(priv); |
1998 | |||
1999 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2000 | } | 2022 | } |
2001 | 2023 | ||
2002 | #define IPW_CMD(x) case IPW_CMD_ ## x : return #x | 2024 | #define IPW_CMD(x) case IPW_CMD_ ## x : return #x |
@@ -10460,7 +10482,7 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) | |||
10460 | if (!priv) | 10482 | if (!priv) |
10461 | return IRQ_NONE; | 10483 | return IRQ_NONE; |
10462 | 10484 | ||
10463 | spin_lock(&priv->lock); | 10485 | spin_lock(&priv->irq_lock); |
10464 | 10486 | ||
10465 | if (!(priv->status & STATUS_INT_ENABLED)) { | 10487 | if (!(priv->status & STATUS_INT_ENABLED)) { |
10466 | /* Shared IRQ */ | 10488 | /* Shared IRQ */ |
@@ -10482,7 +10504,7 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) | |||
10482 | } | 10504 | } |
10483 | 10505 | ||
10484 | /* tell the device to stop sending interrupts */ | 10506 | /* tell the device to stop sending interrupts */ |
10485 | ipw_disable_interrupts(priv); | 10507 | __ipw_disable_interrupts(priv); |
10486 | 10508 | ||
10487 | /* ack current interrupts */ | 10509 | /* ack current interrupts */ |
10488 | inta &= (IPW_INTA_MASK_ALL & inta_mask); | 10510 | inta &= (IPW_INTA_MASK_ALL & inta_mask); |
@@ -10493,11 +10515,11 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) | |||
10493 | 10515 | ||
10494 | tasklet_schedule(&priv->irq_tasklet); | 10516 | tasklet_schedule(&priv->irq_tasklet); |
10495 | 10517 | ||
10496 | spin_unlock(&priv->lock); | 10518 | spin_unlock(&priv->irq_lock); |
10497 | 10519 | ||
10498 | return IRQ_HANDLED; | 10520 | return IRQ_HANDLED; |
10499 | none: | 10521 | none: |
10500 | spin_unlock(&priv->lock); | 10522 | spin_unlock(&priv->irq_lock); |
10501 | return IRQ_NONE; | 10523 | return IRQ_NONE; |
10502 | } | 10524 | } |
10503 | 10525 | ||
@@ -11477,6 +11499,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
11477 | #ifdef CONFIG_IPW2200_DEBUG | 11499 | #ifdef CONFIG_IPW2200_DEBUG |
11478 | ipw_debug_level = debug; | 11500 | ipw_debug_level = debug; |
11479 | #endif | 11501 | #endif |
11502 | spin_lock_init(&priv->irq_lock); | ||
11480 | spin_lock_init(&priv->lock); | 11503 | spin_lock_init(&priv->lock); |
11481 | for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) | 11504 | for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) |
11482 | INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); | 11505 | INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); |
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 6044c0be2c80..ea12ad66b8e8 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h | |||
@@ -1173,6 +1173,7 @@ struct ipw_priv { | |||
1173 | struct ieee80211_device *ieee; | 1173 | struct ieee80211_device *ieee; |
1174 | 1174 | ||
1175 | spinlock_t lock; | 1175 | spinlock_t lock; |
1176 | spinlock_t irq_lock; | ||
1176 | struct mutex mutex; | 1177 | struct mutex mutex; |
1177 | 1178 | ||
1178 | /* basic pci-network driver stuff */ | 1179 | /* basic pci-network driver stuff */ |