aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/airo.c12
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h116
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c80
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h1
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_leds.c10
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c743
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.h3
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c33
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.c4
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c104
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.c166
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.c5
-rw-r--r--drivers/net/wireless/ipw2200.c29
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c573
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.h6
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.c4
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.h2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_netdev.c17
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c2
19 files changed, 1329 insertions, 581 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index a4dd13942714..16befbcea58c 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -3950,13 +3950,11 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
3950 pRsp->rsp0 = IN4500(ai, RESP0); 3950 pRsp->rsp0 = IN4500(ai, RESP0);
3951 pRsp->rsp1 = IN4500(ai, RESP1); 3951 pRsp->rsp1 = IN4500(ai, RESP1);
3952 pRsp->rsp2 = IN4500(ai, RESP2); 3952 pRsp->rsp2 = IN4500(ai, RESP2);
3953 if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) { 3953 if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET)
3954 airo_print_err(ai->dev->name, "cmd= %x\n", pCmd->cmd); 3954 airo_print_err(ai->dev->name,
3955 airo_print_err(ai->dev->name, "status= %x\n", pRsp->status); 3955 "cmd:%x status:%x rsp0:%x rsp1:%x rsp2:%x",
3956 airo_print_err(ai->dev->name, "Rsp0= %x\n", pRsp->rsp0); 3956 pCmd->cmd, pRsp->status, pRsp->rsp0, pRsp->rsp1,
3957 airo_print_err(ai->dev->name, "Rsp1= %x\n", pRsp->rsp1); 3957 pRsp->rsp2);
3958 airo_print_err(ai->dev->name, "Rsp2= %x\n", pRsp->rsp2);
3959 }
3960 3958
3961 // clear stuck command busy if necessary 3959 // clear stuck command busy if necessary
3962 if (IN4500(ai, COMMAND) & COMMAND_BUSY) { 3960 if (IN4500(ai, COMMAND) & COMMAND_BUSY) {
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 17a56828e232..c6ee1e974c84 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -504,6 +504,12 @@ struct bcm43xx_phyinfo {
504 * This lock is only used by bcm43xx_phy_{un}lock() 504 * This lock is only used by bcm43xx_phy_{un}lock()
505 */ 505 */
506 spinlock_t lock; 506 spinlock_t lock;
507
508 /* Firmware. */
509 const struct firmware *ucode;
510 const struct firmware *pcm;
511 const struct firmware *initvals0;
512 const struct firmware *initvals1;
507}; 513};
508 514
509 515
@@ -593,12 +599,14 @@ struct bcm43xx_coreinfo {
593 u8 available:1, 599 u8 available:1,
594 enabled:1, 600 enabled:1,
595 initialized:1; 601 initialized:1;
596 /** core_id ID number */
597 u16 id;
598 /** core_rev revision number */ 602 /** core_rev revision number */
599 u8 rev; 603 u8 rev;
600 /** Index number for _switch_core() */ 604 /** Index number for _switch_core() */
601 u8 index; 605 u8 index;
606 /** core_id ID number */
607 u16 id;
608 /** Core-specific data. */
609 void *priv;
602}; 610};
603 611
604/* Additional information for each 80211 core. */ 612/* Additional information for each 80211 core. */
@@ -647,7 +655,23 @@ enum {
647 BCM43xx_STAT_RESTARTING, /* controller_restart() called. */ 655 BCM43xx_STAT_RESTARTING, /* controller_restart() called. */
648}; 656};
649#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status) 657#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status)
650#define bcm43xx_set_status(bcm, stat) atomic_set(&(bcm)->init_status, (stat)) 658#define bcm43xx_set_status(bcm, stat) do { \
659 atomic_set(&(bcm)->init_status, (stat)); \
660 smp_wmb(); \
661 } while (0)
662
663/* *** THEORY OF LOCKING ***
664 *
665 * We have two different locks in the bcm43xx driver.
666 * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private
667 * and the device registers. This mutex does _not_ protect
668 * against concurrency from the IRQ handler.
669 * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
670 *
671 * Please note that, if you only take the irq_lock, you are not protected
672 * against concurrency from the periodic work handlers.
673 * Most times you want to take _both_ locks.
674 */
651 675
652struct bcm43xx_private { 676struct bcm43xx_private {
653 struct ieee80211_device *ieee; 677 struct ieee80211_device *ieee;
@@ -659,7 +683,6 @@ struct bcm43xx_private {
659 683
660 void __iomem *mmio_addr; 684 void __iomem *mmio_addr;
661 685
662 /* Locking, see "theory of locking" text below. */
663 spinlock_t irq_lock; 686 spinlock_t irq_lock;
664 struct mutex mutex; 687 struct mutex mutex;
665 688
@@ -691,6 +714,7 @@ struct bcm43xx_private {
691 struct bcm43xx_sprominfo sprom; 714 struct bcm43xx_sprominfo sprom;
692#define BCM43xx_NR_LEDS 4 715#define BCM43xx_NR_LEDS 4
693 struct bcm43xx_led leds[BCM43xx_NR_LEDS]; 716 struct bcm43xx_led leds[BCM43xx_NR_LEDS];
717 spinlock_t leds_lock;
694 718
695 /* The currently active core. */ 719 /* The currently active core. */
696 struct bcm43xx_coreinfo *current_core; 720 struct bcm43xx_coreinfo *current_core;
@@ -708,10 +732,6 @@ struct bcm43xx_private {
708 struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ]; 732 struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
709 /* Additional information, specific to the 80211 cores. */ 733 /* Additional information, specific to the 80211 cores. */
710 struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ]; 734 struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
711 /* Index of the current 80211 core. If current_core is not
712 * an 80211 core, this is -1.
713 */
714 int current_80211_core_idx;
715 /* Number of available 80211 cores. */ 735 /* Number of available 80211 cores. */
716 int nr_80211_available; 736 int nr_80211_available;
717 737
@@ -724,6 +744,8 @@ struct bcm43xx_private {
724 u32 irq_savedstate; 744 u32 irq_savedstate;
725 /* Link Quality calculation context. */ 745 /* Link Quality calculation context. */
726 struct bcm43xx_noise_calculation noisecalc; 746 struct bcm43xx_noise_calculation noisecalc;
747 /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
748 int mac_suspended;
727 749
728 /* Threshold values. */ 750 /* Threshold values. */
729 //TODO: The RTS thr has to be _used_. Currently, it is only set via WX. 751 //TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
@@ -746,12 +768,6 @@ struct bcm43xx_private {
746 struct bcm43xx_key key[54]; 768 struct bcm43xx_key key[54];
747 u8 default_key_idx; 769 u8 default_key_idx;
748 770
749 /* Firmware. */
750 const struct firmware *ucode;
751 const struct firmware *pcm;
752 const struct firmware *initvals0;
753 const struct firmware *initvals1;
754
755 /* Random Number Generator. */ 771 /* Random Number Generator. */
756 struct hwrng rng; 772 struct hwrng rng;
757 char rng_name[20 + 1]; 773 char rng_name[20 + 1];
@@ -763,55 +779,6 @@ struct bcm43xx_private {
763}; 779};
764 780
765 781
766/* *** THEORY OF LOCKING ***
767 *
768 * We have two different locks in the bcm43xx driver.
769 * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private
770 * and the device registers.
771 * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
772 *
773 * We have three types of helper function pairs to utilize these locks.
774 * (Always use the helper functions.)
775 * 1) bcm43xx_{un}lock_noirq():
776 * Takes bcm->mutex. Does _not_ protect against IRQ concurrency,
777 * so it is almost always unsafe, if device IRQs are enabled.
778 * So only use this, if device IRQs are masked.
779 * Locking may sleep.
780 * You can sleep within the critical section.
781 * 2) bcm43xx_{un}lock_irqonly():
782 * Takes bcm->irq_lock. Does _not_ protect against
783 * bcm43xx_lock_noirq() critical sections.
784 * Does only protect against the IRQ handler path and other
785 * irqonly() critical sections.
786 * Locking does not sleep.
787 * You must not sleep within the critical section.
788 * 3) bcm43xx_{un}lock_irqsafe():
789 * This is the cummulative lock and takes both, mutex and irq_lock.
790 * Protects against noirq() and irqonly() critical sections (and
791 * the IRQ handler path).
792 * Locking may sleep.
793 * You must not sleep within the critical section.
794 */
795
796/* Lock type 1 */
797#define bcm43xx_lock_noirq(bcm) mutex_lock(&(bcm)->mutex)
798#define bcm43xx_unlock_noirq(bcm) mutex_unlock(&(bcm)->mutex)
799/* Lock type 2 */
800#define bcm43xx_lock_irqonly(bcm, flags) \
801 spin_lock_irqsave(&(bcm)->irq_lock, flags)
802#define bcm43xx_unlock_irqonly(bcm, flags) \
803 spin_unlock_irqrestore(&(bcm)->irq_lock, flags)
804/* Lock type 3 */
805#define bcm43xx_lock_irqsafe(bcm, flags) do { \
806 bcm43xx_lock_noirq(bcm); \
807 bcm43xx_lock_irqonly(bcm, flags); \
808 } while (0)
809#define bcm43xx_unlock_irqsafe(bcm, flags) do { \
810 bcm43xx_unlock_irqonly(bcm, flags); \
811 bcm43xx_unlock_noirq(bcm); \
812 } while (0)
813
814
815static inline 782static inline
816struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) 783struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
817{ 784{
@@ -863,34 +830,33 @@ int bcm43xx_using_pio(struct bcm43xx_private *bcm)
863 * any of these functions. 830 * any of these functions.
864 */ 831 */
865static inline 832static inline
833struct bcm43xx_coreinfo_80211 *
834bcm43xx_current_80211_priv(struct bcm43xx_private *bcm)
835{
836 assert(bcm->current_core->id == BCM43xx_COREID_80211);
837 return bcm->current_core->priv;
838}
839static inline
866struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm) 840struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
867{ 841{
868 assert(bcm43xx_using_pio(bcm)); 842 assert(bcm43xx_using_pio(bcm));
869 assert(bcm->current_80211_core_idx >= 0); 843 return &(bcm43xx_current_80211_priv(bcm)->pio);
870 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
871 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio);
872} 844}
873static inline 845static inline
874struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm) 846struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
875{ 847{
876 assert(!bcm43xx_using_pio(bcm)); 848 assert(!bcm43xx_using_pio(bcm));
877 assert(bcm->current_80211_core_idx >= 0); 849 return &(bcm43xx_current_80211_priv(bcm)->dma);
878 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
879 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma);
880} 850}
881static inline 851static inline
882struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm) 852struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
883{ 853{
884 assert(bcm->current_80211_core_idx >= 0); 854 return &(bcm43xx_current_80211_priv(bcm)->phy);
885 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
886 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy);
887} 855}
888static inline 856static inline
889struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm) 857struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
890{ 858{
891 assert(bcm->current_80211_core_idx >= 0); 859 return &(bcm43xx_current_80211_priv(bcm)->radio);
892 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
893 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
894} 860}
895 861
896 862
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
index ce2e40b29b4f..923275ea0789 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -77,7 +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_irqsafe(bcm, flags); 80 mutex_lock(&bcm->mutex);
81 spin_lock_irqsave(&bcm->irq_lock, flags);
81 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { 82 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
82 fappend("Board not initialized.\n"); 83 fappend("Board not initialized.\n");
83 goto out; 84 goto out;
@@ -121,7 +122,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
121 fappend("\n"); 122 fappend("\n");
122 123
123out: 124out:
124 bcm43xx_unlock_irqsafe(bcm, flags); 125 spin_unlock_irqrestore(&bcm->irq_lock, flags);
126 mutex_unlock(&bcm->mutex);
125 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 127 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
126 up(&big_buffer_sem); 128 up(&big_buffer_sem);
127 return res; 129 return res;
@@ -159,7 +161,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
159 unsigned long flags; 161 unsigned long flags;
160 162
161 down(&big_buffer_sem); 163 down(&big_buffer_sem);
162 bcm43xx_lock_irqsafe(bcm, flags); 164 mutex_lock(&bcm->mutex);
165 spin_lock_irqsave(&bcm->irq_lock, flags);
163 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { 166 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
164 fappend("Board not initialized.\n"); 167 fappend("Board not initialized.\n");
165 goto out; 168 goto out;
@@ -169,7 +172,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
169 fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); 172 fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
170 173
171out: 174out:
172 bcm43xx_unlock_irqsafe(bcm, flags); 175 spin_unlock_irqrestore(&bcm->irq_lock, flags);
176 mutex_unlock(&bcm->mutex);
173 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 177 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
174 up(&big_buffer_sem); 178 up(&big_buffer_sem);
175 return res; 179 return res;
@@ -188,7 +192,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
188 u64 tsf; 192 u64 tsf;
189 193
190 down(&big_buffer_sem); 194 down(&big_buffer_sem);
191 bcm43xx_lock_irqsafe(bcm, flags); 195 mutex_lock(&bcm->mutex);
196 spin_lock_irqsave(&bcm->irq_lock, flags);
192 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { 197 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
193 fappend("Board not initialized.\n"); 198 fappend("Board not initialized.\n");
194 goto out; 199 goto out;
@@ -199,7 +204,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
199 (unsigned int)(tsf & 0xFFFFFFFFULL)); 204 (unsigned int)(tsf & 0xFFFFFFFFULL));
200 205
201out: 206out:
202 bcm43xx_unlock_irqsafe(bcm, flags); 207 spin_unlock_irqrestore(&bcm->irq_lock, flags);
208 mutex_unlock(&bcm->mutex);
203 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 209 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
204 up(&big_buffer_sem); 210 up(&big_buffer_sem);
205 return res; 211 return res;
@@ -221,7 +227,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
221 res = -EFAULT; 227 res = -EFAULT;
222 goto out_up; 228 goto out_up;
223 } 229 }
224 bcm43xx_lock_irqsafe(bcm, flags); 230 mutex_lock(&bcm->mutex);
231 spin_lock_irqsave(&bcm->irq_lock, flags);
225 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { 232 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
226 printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); 233 printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
227 res = -EFAULT; 234 res = -EFAULT;
@@ -237,7 +244,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
237 res = buf_size; 244 res = buf_size;
238 245
239out_unlock: 246out_unlock:
240 bcm43xx_unlock_irqsafe(bcm, flags); 247 spin_unlock_irqrestore(&bcm->irq_lock, flags);
248 mutex_unlock(&bcm->mutex);
241out_up: 249out_up:
242 up(&big_buffer_sem); 250 up(&big_buffer_sem);
243 return res; 251 return res;
@@ -258,7 +266,8 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
258 int i, cnt, j = 0; 266 int i, cnt, j = 0;
259 267
260 down(&big_buffer_sem); 268 down(&big_buffer_sem);
261 bcm43xx_lock_irqsafe(bcm, flags); 269 mutex_lock(&bcm->mutex);
270 spin_lock_irqsave(&bcm->irq_lock, flags);
262 271
263 fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", 272 fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
264 BCM43xx_NR_LOGGED_XMITSTATUS); 273 BCM43xx_NR_LOGGED_XMITSTATUS);
@@ -294,14 +303,51 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
294 i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; 303 i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
295 } 304 }
296 305
297 bcm43xx_unlock_irqsafe(bcm, flags); 306 spin_unlock_irqrestore(&bcm->irq_lock, flags);
298 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 307 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
299 bcm43xx_lock_irqsafe(bcm, flags); 308 spin_lock_irqsave(&bcm->irq_lock, flags);
300 if (*ppos == pos) { 309 if (*ppos == pos) {
301 /* Done. Drop the copied data. */ 310 /* Done. Drop the copied data. */
302 e->xmitstatus_printing = 0; 311 e->xmitstatus_printing = 0;
303 } 312 }
304 bcm43xx_unlock_irqsafe(bcm, flags); 313 spin_unlock_irqrestore(&bcm->irq_lock, flags);
314 mutex_unlock(&bcm->mutex);
315 up(&big_buffer_sem);
316 return res;
317}
318
319static ssize_t restart_write_file(struct file *file, const char __user *user_buf,
320 size_t count, loff_t *ppos)
321{
322 struct bcm43xx_private *bcm = file->private_data;
323 char *buf = really_big_buffer;
324 ssize_t buf_size;
325 ssize_t res;
326 unsigned long flags;
327
328 buf_size = min(count, sizeof (really_big_buffer) - 1);
329 down(&big_buffer_sem);
330 if (copy_from_user(buf, user_buf, buf_size)) {
331 res = -EFAULT;
332 goto out_up;
333 }
334 mutex_lock(&(bcm)->mutex);
335 spin_lock_irqsave(&(bcm)->irq_lock, flags);
336 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
337 printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
338 res = -EFAULT;
339 goto out_unlock;
340 }
341 if (count > 0 && buf[0] == '1') {
342 bcm43xx_controller_restart(bcm, "manually restarted");
343 res = count;
344 } else
345 res = -EINVAL;
346
347out_unlock:
348 spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
349 mutex_unlock(&(bcm)->mutex);
350out_up:
305 up(&big_buffer_sem); 351 up(&big_buffer_sem);
306 return res; 352 return res;
307} 353}
@@ -339,6 +385,11 @@ static struct file_operations txstat_fops = {
339 .open = open_file_generic, 385 .open = open_file_generic,
340}; 386};
341 387
388static struct file_operations restart_fops = {
389 .write = restart_write_file,
390 .open = open_file_generic,
391};
392
342 393
343void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) 394void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
344{ 395{
@@ -390,6 +441,10 @@ void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
390 bcm, &txstat_fops); 441 bcm, &txstat_fops);
391 if (!e->dentry_txstat) 442 if (!e->dentry_txstat)
392 printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir); 443 printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
444 e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir,
445 bcm, &restart_fops);
446 if (!e->dentry_restart)
447 printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir);
393} 448}
394 449
395void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) 450void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
@@ -405,6 +460,7 @@ void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
405 debugfs_remove(e->dentry_devinfo); 460 debugfs_remove(e->dentry_devinfo);
406 debugfs_remove(e->dentry_tsf); 461 debugfs_remove(e->dentry_tsf);
407 debugfs_remove(e->dentry_txstat); 462 debugfs_remove(e->dentry_txstat);
463 debugfs_remove(e->dentry_restart);
408 debugfs_remove(e->subdir); 464 debugfs_remove(e->subdir);
409 kfree(e->xmitstatus_buffer); 465 kfree(e->xmitstatus_buffer);
410 kfree(e->xmitstatus_print_buffer); 466 kfree(e->xmitstatus_print_buffer);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
index 50ce267f794d..a40d1af35545 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
@@ -20,6 +20,7 @@ struct bcm43xx_dfsentry {
20 struct dentry *dentry_spromdump; 20 struct dentry *dentry_spromdump;
21 struct dentry *dentry_tsf; 21 struct dentry *dentry_tsf;
22 struct dentry *dentry_txstat; 22 struct dentry *dentry_txstat;
23 struct dentry *dentry_restart;
23 24
24 struct bcm43xx_private *bcm; 25 struct bcm43xx_private *bcm;
25 26
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
index ec80692d638a..c3f90c8563d9 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_irqonly(bcm, flags); 54 spin_lock_irqsave(&bcm->leds_lock, 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_irqonly(bcm, flags); 59 spin_unlock_irqrestore(&bcm->leds_lock, flags);
60} 60}
61 61
62static void bcm43xx_led_blink_start(struct bcm43xx_led *led, 62static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
@@ -177,7 +177,9 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
177 int i, turn_on; 177 int i, turn_on;
178 unsigned long interval = 0; 178 unsigned long interval = 0;
179 u16 ledctl; 179 u16 ledctl;
180 unsigned long flags;
180 181
182 spin_lock_irqsave(&bcm->leds_lock, flags);
181 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); 183 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
182 for (i = 0; i < BCM43xx_NR_LEDS; i++) { 184 for (i = 0; i < BCM43xx_NR_LEDS; i++) {
183 led = &(bcm->leds[i]); 185 led = &(bcm->leds[i]);
@@ -266,6 +268,7 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
266 ledctl &= ~(1 << i); 268 ledctl &= ~(1 << i);
267 } 269 }
268 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); 270 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
271 spin_unlock_irqrestore(&bcm->leds_lock, flags);
269} 272}
270 273
271void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) 274void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
@@ -274,7 +277,9 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
274 u16 ledctl; 277 u16 ledctl;
275 int i; 278 int i;
276 int bit_on; 279 int bit_on;
280 unsigned long flags;
277 281
282 spin_lock_irqsave(&bcm->leds_lock, flags);
278 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); 283 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
279 for (i = 0; i < BCM43xx_NR_LEDS; i++) { 284 for (i = 0; i < BCM43xx_NR_LEDS; i++) {
280 led = &(bcm->leds[i]); 285 led = &(bcm->leds[i]);
@@ -290,4 +295,5 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
290 ledctl &= ~(1 << i); 295 ledctl &= ~(1 << i);
291 } 296 }
292 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); 297 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
298 spin_unlock_irqrestore(&bcm->leds_lock, flags);
293} 299}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index df317c1e12a8..b095f3cc6730 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -509,23 +509,19 @@ static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm)
509} 509}
510 510
511/* Make sure we don't receive more data from the device. */ 511/* Make sure we don't receive more data from the device. */
512static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate) 512static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm)
513{ 513{
514 unsigned long flags; 514 unsigned long flags;
515 u32 old;
516 515
517 bcm43xx_lock_irqonly(bcm, flags); 516 spin_lock_irqsave(&bcm->irq_lock, flags);
518 if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { 517 if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
519 bcm43xx_unlock_irqonly(bcm, flags); 518 spin_unlock_irqrestore(&bcm->irq_lock, flags);
520 return -EBUSY; 519 return -EBUSY;
521 } 520 }
522 old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 521 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
523 bcm43xx_unlock_irqonly(bcm, flags); 522 spin_unlock_irqrestore(&bcm->irq_lock, flags);
524 bcm43xx_synchronize_irq(bcm); 523 bcm43xx_synchronize_irq(bcm);
525 524
526 if (oldstate)
527 *oldstate = old;
528
529 return 0; 525 return 0;
530} 526}
531 527
@@ -537,7 +533,6 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
537 u16 manufact; 533 u16 manufact;
538 u16 version; 534 u16 version;
539 u8 revision; 535 u8 revision;
540 s8 i;
541 536
542 if (bcm->chip_id == 0x4317) { 537 if (bcm->chip_id == 0x4317) {
543 if (bcm->chip_rev == 0x00) 538 if (bcm->chip_rev == 0x00)
@@ -580,20 +575,11 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
580 radio->version = version; 575 radio->version = version;
581 radio->revision = revision; 576 radio->revision = revision;
582 577
583 /* Set default attenuation values. */
584 radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
585 radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
586 radio->txctl1 = bcm43xx_default_txctl1(bcm);
587 radio->txctl2 = 0xFFFF;
588 if (phy->type == BCM43xx_PHYTYPE_A) 578 if (phy->type == BCM43xx_PHYTYPE_A)
589 radio->txpower_desired = bcm->sprom.maxpower_aphy; 579 radio->txpower_desired = bcm->sprom.maxpower_aphy;
590 else 580 else
591 radio->txpower_desired = bcm->sprom.maxpower_bgphy; 581 radio->txpower_desired = bcm->sprom.maxpower_bgphy;
592 582
593 /* Initialize the in-memory nrssi Lookup Table. */
594 for (i = 0; i < 64; i++)
595 radio->nrssi_lt[i] = i;
596
597 return 0; 583 return 0;
598 584
599err_unsupported_radio: 585err_unsupported_radio:
@@ -1250,10 +1236,6 @@ int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *ne
1250 goto out; 1236 goto out;
1251 1237
1252 bcm->current_core = new_core; 1238 bcm->current_core = new_core;
1253 bcm->current_80211_core_idx = -1;
1254 if (new_core->id == BCM43xx_COREID_80211)
1255 bcm->current_80211_core_idx = (int)(new_core - &(bcm->core_80211[0]));
1256
1257out: 1239out:
1258 return err; 1240 return err;
1259} 1241}
@@ -1423,43 +1405,23 @@ static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm)
1423 bcm43xx_core_disable(bcm, 0); 1405 bcm43xx_core_disable(bcm, 0);
1424} 1406}
1425 1407
1426/* Mark the current 80211 core inactive. 1408/* Mark the current 80211 core inactive. */
1427 * "active_80211_core" is the other 80211 core, which is used. 1409static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm)
1428 */
1429static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm,
1430 struct bcm43xx_coreinfo *active_80211_core)
1431{ 1410{
1432 u32 sbtmstatelow; 1411 u32 sbtmstatelow;
1433 struct bcm43xx_coreinfo *old_core;
1434 int err = 0;
1435 1412
1436 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 1413 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
1437 bcm43xx_radio_turn_off(bcm); 1414 bcm43xx_radio_turn_off(bcm);
1438 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); 1415 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1439 sbtmstatelow &= ~0x200a0000; 1416 sbtmstatelow &= 0xDFF5FFFF;
1440 sbtmstatelow |= 0xa0000; 1417 sbtmstatelow |= 0x000A0000;
1441 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); 1418 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1442 udelay(1); 1419 udelay(1);
1443 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); 1420 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1444 sbtmstatelow &= ~0xa0000; 1421 sbtmstatelow &= 0xFFF5FFFF;
1445 sbtmstatelow |= 0x80000; 1422 sbtmstatelow |= 0x00080000;
1446 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); 1423 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1447 udelay(1); 1424 udelay(1);
1448
1449 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G) {
1450 old_core = bcm->current_core;
1451 err = bcm43xx_switch_core(bcm, active_80211_core);
1452 if (err)
1453 goto out;
1454 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1455 sbtmstatelow &= ~0x20000000;
1456 sbtmstatelow |= 0x20000000;
1457 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1458 err = bcm43xx_switch_core(bcm, old_core);
1459 }
1460
1461out:
1462 return err;
1463} 1425}
1464 1426
1465static void handle_irq_transmit_status(struct bcm43xx_private *bcm) 1427static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
@@ -1720,7 +1682,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
1720# define bcmirq_handled(irq) do { /* nothing */ } while (0) 1682# define bcmirq_handled(irq) do { /* nothing */ } while (0)
1721#endif /* CONFIG_BCM43XX_DEBUG*/ 1683#endif /* CONFIG_BCM43XX_DEBUG*/
1722 1684
1723 bcm43xx_lock_irqonly(bcm, flags); 1685 spin_lock_irqsave(&bcm->irq_lock, flags);
1724 reason = bcm->irq_reason; 1686 reason = bcm->irq_reason;
1725 dma_reason[0] = bcm->dma_reason[0]; 1687 dma_reason[0] = bcm->dma_reason[0];
1726 dma_reason[1] = bcm->dma_reason[1]; 1688 dma_reason[1] = bcm->dma_reason[1];
@@ -1746,7 +1708,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
1746 dma_reason[2], dma_reason[3]); 1708 dma_reason[2], dma_reason[3]);
1747 bcm43xx_controller_restart(bcm, "DMA error"); 1709 bcm43xx_controller_restart(bcm, "DMA error");
1748 mmiowb(); 1710 mmiowb();
1749 bcm43xx_unlock_irqonly(bcm, flags); 1711 spin_unlock_irqrestore(&bcm->irq_lock, flags);
1750 return; 1712 return;
1751 } 1713 }
1752 if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) | 1714 if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
@@ -1834,7 +1796,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
1834 bcm43xx_leds_update(bcm, activity); 1796 bcm43xx_leds_update(bcm, activity);
1835 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); 1797 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
1836 mmiowb(); 1798 mmiowb();
1837 bcm43xx_unlock_irqonly(bcm, flags); 1799 spin_unlock_irqrestore(&bcm->irq_lock, flags);
1838} 1800}
1839 1801
1840static void pio_irq_workaround(struct bcm43xx_private *bcm, 1802static void pio_irq_workaround(struct bcm43xx_private *bcm,
@@ -1885,14 +1847,8 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
1885 1847
1886 spin_lock(&bcm->irq_lock); 1848 spin_lock(&bcm->irq_lock);
1887 1849
1888 /* Only accept IRQs, if we are initialized properly. 1850 assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
1889 * This avoids an RX race while initializing. 1851 assert(bcm->current_core->id == BCM43xx_COREID_80211);
1890 * We should probably not enable IRQs before we are initialized
1891 * completely, but some careful work is needed to fix this. I think it
1892 * is best to stay with this cheap workaround for now... .
1893 */
1894 if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED))
1895 goto out;
1896 1852
1897 reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); 1853 reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
1898 if (reason == 0xffffffff) { 1854 if (reason == 0xffffffff) {
@@ -1930,16 +1886,18 @@ out:
1930 1886
1931static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) 1887static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
1932{ 1888{
1889 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1890
1933 if (bcm->firmware_norelease && !force) 1891 if (bcm->firmware_norelease && !force)
1934 return; /* Suspending or controller reset. */ 1892 return; /* Suspending or controller reset. */
1935 release_firmware(bcm->ucode); 1893 release_firmware(phy->ucode);
1936 bcm->ucode = NULL; 1894 phy->ucode = NULL;
1937 release_firmware(bcm->pcm); 1895 release_firmware(phy->pcm);
1938 bcm->pcm = NULL; 1896 phy->pcm = NULL;
1939 release_firmware(bcm->initvals0); 1897 release_firmware(phy->initvals0);
1940 bcm->initvals0 = NULL; 1898 phy->initvals0 = NULL;
1941 release_firmware(bcm->initvals1); 1899 release_firmware(phy->initvals1);
1942 bcm->initvals1 = NULL; 1900 phy->initvals1 = NULL;
1943} 1901}
1944 1902
1945static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) 1903static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
@@ -1950,11 +1908,11 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
1950 int nr; 1908 int nr;
1951 char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 }; 1909 char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
1952 1910
1953 if (!bcm->ucode) { 1911 if (!phy->ucode) {
1954 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw", 1912 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
1955 (rev >= 5 ? 5 : rev), 1913 (rev >= 5 ? 5 : rev),
1956 modparam_fwpostfix); 1914 modparam_fwpostfix);
1957 err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev); 1915 err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev);
1958 if (err) { 1916 if (err) {
1959 printk(KERN_ERR PFX 1917 printk(KERN_ERR PFX
1960 "Error: Microcode \"%s\" not available or load failed.\n", 1918 "Error: Microcode \"%s\" not available or load failed.\n",
@@ -1963,12 +1921,12 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
1963 } 1921 }
1964 } 1922 }
1965 1923
1966 if (!bcm->pcm) { 1924 if (!phy->pcm) {
1967 snprintf(buf, ARRAY_SIZE(buf), 1925 snprintf(buf, ARRAY_SIZE(buf),
1968 "bcm43xx_pcm%d%s.fw", 1926 "bcm43xx_pcm%d%s.fw",
1969 (rev < 5 ? 4 : 5), 1927 (rev < 5 ? 4 : 5),
1970 modparam_fwpostfix); 1928 modparam_fwpostfix);
1971 err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev); 1929 err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev);
1972 if (err) { 1930 if (err) {
1973 printk(KERN_ERR PFX 1931 printk(KERN_ERR PFX
1974 "Error: PCM \"%s\" not available or load failed.\n", 1932 "Error: PCM \"%s\" not available or load failed.\n",
@@ -1977,7 +1935,7 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
1977 } 1935 }
1978 } 1936 }
1979 1937
1980 if (!bcm->initvals0) { 1938 if (!phy->initvals0) {
1981 if (rev == 2 || rev == 4) { 1939 if (rev == 2 || rev == 4) {
1982 switch (phy->type) { 1940 switch (phy->type) {
1983 case BCM43xx_PHYTYPE_A: 1941 case BCM43xx_PHYTYPE_A:
@@ -2008,20 +1966,20 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
2008 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", 1966 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
2009 nr, modparam_fwpostfix); 1967 nr, modparam_fwpostfix);
2010 1968
2011 err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev); 1969 err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev);
2012 if (err) { 1970 if (err) {
2013 printk(KERN_ERR PFX 1971 printk(KERN_ERR PFX
2014 "Error: InitVals \"%s\" not available or load failed.\n", 1972 "Error: InitVals \"%s\" not available or load failed.\n",
2015 buf); 1973 buf);
2016 goto error; 1974 goto error;
2017 } 1975 }
2018 if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) { 1976 if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) {
2019 printk(KERN_ERR PFX "InitVals fileformat error.\n"); 1977 printk(KERN_ERR PFX "InitVals fileformat error.\n");
2020 goto error; 1978 goto error;
2021 } 1979 }
2022 } 1980 }
2023 1981
2024 if (!bcm->initvals1) { 1982 if (!phy->initvals1) {
2025 if (rev >= 5) { 1983 if (rev >= 5) {
2026 u32 sbtmstatehigh; 1984 u32 sbtmstatehigh;
2027 1985
@@ -2043,14 +2001,14 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
2043 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", 2001 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
2044 nr, modparam_fwpostfix); 2002 nr, modparam_fwpostfix);
2045 2003
2046 err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev); 2004 err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev);
2047 if (err) { 2005 if (err) {
2048 printk(KERN_ERR PFX 2006 printk(KERN_ERR PFX
2049 "Error: InitVals \"%s\" not available or load failed.\n", 2007 "Error: InitVals \"%s\" not available or load failed.\n",
2050 buf); 2008 buf);
2051 goto error; 2009 goto error;
2052 } 2010 }
2053 if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) { 2011 if (phy->initvals1->size % sizeof(struct bcm43xx_initval)) {
2054 printk(KERN_ERR PFX "InitVals fileformat error.\n"); 2012 printk(KERN_ERR PFX "InitVals fileformat error.\n");
2055 goto error; 2013 goto error;
2056 } 2014 }
@@ -2070,12 +2028,13 @@ err_noinitval:
2070 2028
2071static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) 2029static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
2072{ 2030{
2031 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2073 const u32 *data; 2032 const u32 *data;
2074 unsigned int i, len; 2033 unsigned int i, len;
2075 2034
2076 /* Upload Microcode. */ 2035 /* Upload Microcode. */
2077 data = (u32 *)(bcm->ucode->data); 2036 data = (u32 *)(phy->ucode->data);
2078 len = bcm->ucode->size / sizeof(u32); 2037 len = phy->ucode->size / sizeof(u32);
2079 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000); 2038 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
2080 for (i = 0; i < len; i++) { 2039 for (i = 0; i < len; i++) {
2081 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 2040 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
@@ -2084,8 +2043,8 @@ static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
2084 } 2043 }
2085 2044
2086 /* Upload PCM data. */ 2045 /* Upload PCM data. */
2087 data = (u32 *)(bcm->pcm->data); 2046 data = (u32 *)(phy->pcm->data);
2088 len = bcm->pcm->size / sizeof(u32); 2047 len = phy->pcm->size / sizeof(u32);
2089 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea); 2048 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
2090 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000); 2049 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
2091 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb); 2050 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
@@ -2131,15 +2090,16 @@ err_format:
2131 2090
2132static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) 2091static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
2133{ 2092{
2093 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2134 int err; 2094 int err;
2135 2095
2136 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, 2096 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data,
2137 bcm->initvals0->size / sizeof(struct bcm43xx_initval)); 2097 phy->initvals0->size / sizeof(struct bcm43xx_initval));
2138 if (err) 2098 if (err)
2139 goto out; 2099 goto out;
2140 if (bcm->initvals1) { 2100 if (phy->initvals1) {
2141 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data, 2101 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data,
2142 bcm->initvals1->size / sizeof(struct bcm43xx_initval)); 2102 phy->initvals1->size / sizeof(struct bcm43xx_initval));
2143 if (err) 2103 if (err)
2144 goto out; 2104 goto out;
2145 } 2105 }
@@ -2156,9 +2116,7 @@ static struct pci_device_id bcm43xx_47xx_ids[] = {
2156 2116
2157static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) 2117static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
2158{ 2118{
2159 int res; 2119 int err;
2160 unsigned int i;
2161 u32 data;
2162 2120
2163 bcm->irq = bcm->pci_dev->irq; 2121 bcm->irq = bcm->pci_dev->irq;
2164#ifdef CONFIG_BCM947XX 2122#ifdef CONFIG_BCM947XX
@@ -2175,32 +2133,12 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
2175 } 2133 }
2176 } 2134 }
2177#endif 2135#endif
2178 res = request_irq(bcm->irq, bcm43xx_interrupt_handler, 2136 err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
2179 IRQF_SHARED, KBUILD_MODNAME, bcm); 2137 IRQF_SHARED, KBUILD_MODNAME, bcm);
2180 if (res) { 2138 if (err)
2181 printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); 2139 printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
2182 return -ENODEV;
2183 }
2184 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff);
2185 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
2186 i = 0;
2187 while (1) {
2188 data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2189 if (data == BCM43xx_IRQ_READY)
2190 break;
2191 i++;
2192 if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
2193 printk(KERN_ERR PFX "Card IRQ register not responding. "
2194 "Giving up.\n");
2195 free_irq(bcm->irq, bcm);
2196 return -ENODEV;
2197 }
2198 udelay(10);
2199 }
2200 // dummy read
2201 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2202 2140
2203 return 0; 2141 return err;
2204} 2142}
2205 2143
2206/* Switch to the core used to write the GPIO register. 2144/* Switch to the core used to write the GPIO register.
@@ -2298,13 +2236,17 @@ static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
2298/* http://bcm-specs.sipsolutions.net/EnableMac */ 2236/* http://bcm-specs.sipsolutions.net/EnableMac */
2299void bcm43xx_mac_enable(struct bcm43xx_private *bcm) 2237void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
2300{ 2238{
2301 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 2239 bcm->mac_suspended--;
2302 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) 2240 assert(bcm->mac_suspended >= 0);
2303 | BCM43xx_SBF_MAC_ENABLED); 2241 if (bcm->mac_suspended == 0) {
2304 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY); 2242 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2305 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ 2243 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2306 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ 2244 | BCM43xx_SBF_MAC_ENABLED);
2307 bcm43xx_power_saving_ctl_bits(bcm, -1, -1); 2245 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
2246 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
2247 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2248 bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
2249 }
2308} 2250}
2309 2251
2310/* http://bcm-specs.sipsolutions.net/SuspendMAC */ 2252/* http://bcm-specs.sipsolutions.net/SuspendMAC */
@@ -2313,18 +2255,23 @@ void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
2313 int i; 2255 int i;
2314 u32 tmp; 2256 u32 tmp;
2315 2257
2316 bcm43xx_power_saving_ctl_bits(bcm, -1, 1); 2258 assert(bcm->mac_suspended >= 0);
2317 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 2259 if (bcm->mac_suspended == 0) {
2318 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) 2260 bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
2319 & ~BCM43xx_SBF_MAC_ENABLED); 2261 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2320 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ 2262 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2321 for (i = 100000; i; i--) { 2263 & ~BCM43xx_SBF_MAC_ENABLED);
2322 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); 2264 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2323 if (tmp & BCM43xx_IRQ_READY) 2265 for (i = 10000; i; i--) {
2324 return; 2266 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2325 udelay(10); 2267 if (tmp & BCM43xx_IRQ_READY)
2268 goto out;
2269 udelay(1);
2270 }
2271 printkl(KERN_ERR PFX "MAC suspend failed\n");
2326 } 2272 }
2327 printkl(KERN_ERR PFX "MAC suspend failed\n"); 2273out:
2274 bcm->mac_suspended++;
2328} 2275}
2329 2276
2330void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, 2277void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
@@ -2394,7 +2341,6 @@ static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
2394 if (!modparam_noleds) 2341 if (!modparam_noleds)
2395 bcm43xx_leds_exit(bcm); 2342 bcm43xx_leds_exit(bcm);
2396 bcm43xx_gpio_cleanup(bcm); 2343 bcm43xx_gpio_cleanup(bcm);
2397 free_irq(bcm->irq, bcm);
2398 bcm43xx_release_firmware(bcm, 0); 2344 bcm43xx_release_firmware(bcm, 0);
2399} 2345}
2400 2346
@@ -2406,7 +2352,7 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
2406 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); 2352 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2407 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 2353 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2408 int err; 2354 int err;
2409 int tmp; 2355 int i, tmp;
2410 u32 value32; 2356 u32 value32;
2411 u16 value16; 2357 u16 value16;
2412 2358
@@ -2419,13 +2365,26 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
2419 goto out; 2365 goto out;
2420 bcm43xx_upload_microcode(bcm); 2366 bcm43xx_upload_microcode(bcm);
2421 2367
2422 err = bcm43xx_initialize_irq(bcm); 2368 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF);
2423 if (err) 2369 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
2424 goto err_release_fw; 2370 i = 0;
2371 while (1) {
2372 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2373 if (value32 == BCM43xx_IRQ_READY)
2374 break;
2375 i++;
2376 if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
2377 printk(KERN_ERR PFX "IRQ_READY timeout\n");
2378 err = -ENODEV;
2379 goto err_release_fw;
2380 }
2381 udelay(10);
2382 }
2383 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2425 2384
2426 err = bcm43xx_gpio_init(bcm); 2385 err = bcm43xx_gpio_init(bcm);
2427 if (err) 2386 if (err)
2428 goto err_free_irq; 2387 goto err_release_fw;
2429 2388
2430 err = bcm43xx_upload_initvals(bcm); 2389 err = bcm43xx_upload_initvals(bcm);
2431 if (err) 2390 if (err)
@@ -2509,8 +2468,6 @@ err_radio_off:
2509 bcm43xx_radio_turn_off(bcm); 2468 bcm43xx_radio_turn_off(bcm);
2510err_gpio_cleanup: 2469err_gpio_cleanup:
2511 bcm43xx_gpio_cleanup(bcm); 2470 bcm43xx_gpio_cleanup(bcm);
2512err_free_irq:
2513 free_irq(bcm->irq, bcm);
2514err_release_fw: 2471err_release_fw:
2515 bcm43xx_release_firmware(bcm, 1); 2472 bcm43xx_release_firmware(bcm, 1);
2516 goto out; 2473 goto out;
@@ -2550,11 +2507,9 @@ static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy)
2550{ 2507{
2551 /* Initialize a "phyinfo" structure. The structure is already 2508 /* Initialize a "phyinfo" structure. The structure is already
2552 * zeroed out. 2509 * zeroed out.
2510 * This is called on insmod time to initialize members.
2553 */ 2511 */
2554 phy->antenna_diversity = 0xFFFF;
2555 phy->savedpctlreg = 0xFFFF; 2512 phy->savedpctlreg = 0xFFFF;
2556 phy->minlowsig[0] = 0xFFFF;
2557 phy->minlowsig[1] = 0xFFFF;
2558 spin_lock_init(&phy->lock); 2513 spin_lock_init(&phy->lock);
2559} 2514}
2560 2515
@@ -2562,14 +2517,11 @@ static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio)
2562{ 2517{
2563 /* Initialize a "radioinfo" structure. The structure is already 2518 /* Initialize a "radioinfo" structure. The structure is already
2564 * zeroed out. 2519 * zeroed out.
2520 * This is called on insmod time to initialize members.
2565 */ 2521 */
2566 radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; 2522 radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
2567 radio->channel = 0xFF; 2523 radio->channel = 0xFF;
2568 radio->initial_channel = 0xFF; 2524 radio->initial_channel = 0xFF;
2569 radio->lofcal = 0xFFFF;
2570 radio->initval = 0xFFFF;
2571 radio->nrssi[0] = -1000;
2572 radio->nrssi[1] = -1000;
2573} 2525}
2574 2526
2575static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) 2527static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
@@ -2587,7 +2539,6 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
2587 * BCM43xx_MAX_80211_CORES); 2539 * BCM43xx_MAX_80211_CORES);
2588 memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211) 2540 memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
2589 * BCM43xx_MAX_80211_CORES); 2541 * BCM43xx_MAX_80211_CORES);
2590 bcm->current_80211_core_idx = -1;
2591 bcm->nr_80211_available = 0; 2542 bcm->nr_80211_available = 0;
2592 bcm->current_core = NULL; 2543 bcm->current_core = NULL;
2593 bcm->active_80211_core = NULL; 2544 bcm->active_80211_core = NULL;
@@ -2757,6 +2708,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
2757 goto out; 2708 goto out;
2758 } 2709 }
2759 bcm->nr_80211_available++; 2710 bcm->nr_80211_available++;
2711 core->priv = ext_80211;
2760 bcm43xx_init_struct_phyinfo(&ext_80211->phy); 2712 bcm43xx_init_struct_phyinfo(&ext_80211->phy);
2761 bcm43xx_init_struct_radioinfo(&ext_80211->radio); 2713 bcm43xx_init_struct_radioinfo(&ext_80211->radio);
2762 break; 2714 break;
@@ -2857,7 +2809,8 @@ static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
2857} 2809}
2858 2810
2859/* http://bcm-specs.sipsolutions.net/80211Init */ 2811/* http://bcm-specs.sipsolutions.net/80211Init */
2860static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) 2812static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
2813 int active_wlcore)
2861{ 2814{
2862 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 2815 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2863 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); 2816 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
@@ -2939,19 +2892,26 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm)
2939 if (bcm->current_core->rev >= 5) 2892 if (bcm->current_core->rev >= 5)
2940 bcm43xx_write16(bcm, 0x043C, 0x000C); 2893 bcm43xx_write16(bcm, 0x043C, 0x000C);
2941 2894
2942 if (bcm43xx_using_pio(bcm)) 2895 if (active_wlcore) {
2943 err = bcm43xx_pio_init(bcm); 2896 if (bcm43xx_using_pio(bcm))
2944 else 2897 err = bcm43xx_pio_init(bcm);
2945 err = bcm43xx_dma_init(bcm); 2898 else
2946 if (err) 2899 err = bcm43xx_dma_init(bcm);
2947 goto err_chip_cleanup; 2900 if (err)
2901 goto err_chip_cleanup;
2902 }
2948 bcm43xx_write16(bcm, 0x0612, 0x0050); 2903 bcm43xx_write16(bcm, 0x0612, 0x0050);
2949 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); 2904 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
2950 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); 2905 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
2951 2906
2952 bcm43xx_mac_enable(bcm); 2907 if (active_wlcore) {
2953 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); 2908 if (radio->initial_channel != 0xFF)
2909 bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0);
2910 }
2954 2911
2912 /* Don't enable MAC/IRQ here, as it will race with the IRQ handler.
2913 * We enable it later.
2914 */
2955 bcm->current_core->initialized = 1; 2915 bcm->current_core->initialized = 1;
2956out: 2916out:
2957 return err; 2917 return err;
@@ -3066,11 +3026,6 @@ out:
3066 return err; 3026 return err;
3067} 3027}
3068 3028
3069static void bcm43xx_softmac_init(struct bcm43xx_private *bcm)
3070{
3071 ieee80211softmac_start(bcm->net_dev);
3072}
3073
3074static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) 3029static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
3075{ 3030{
3076 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 3031 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
@@ -3182,39 +3137,40 @@ static void bcm43xx_periodic_work_handler(void *d)
3182 /* Periodic work will take a long time, so we want it to 3137 /* Periodic work will take a long time, so we want it to
3183 * be preemtible. 3138 * be preemtible.
3184 */ 3139 */
3185 bcm43xx_lock_irqonly(bcm, flags);
3186 netif_stop_queue(bcm->net_dev); 3140 netif_stop_queue(bcm->net_dev);
3141 synchronize_net();
3142 spin_lock_irqsave(&bcm->irq_lock, flags);
3143 bcm43xx_mac_suspend(bcm);
3187 if (bcm43xx_using_pio(bcm)) 3144 if (bcm43xx_using_pio(bcm))
3188 bcm43xx_pio_freeze_txqueues(bcm); 3145 bcm43xx_pio_freeze_txqueues(bcm);
3189 savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 3146 savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3190 bcm43xx_unlock_irqonly(bcm, flags); 3147 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3191 bcm43xx_lock_noirq(bcm); 3148 mutex_lock(&bcm->mutex);
3192 bcm43xx_synchronize_irq(bcm); 3149 bcm43xx_synchronize_irq(bcm);
3193 } else { 3150 } else {
3194 /* Periodic work should take short time, so we want low 3151 /* Periodic work should take short time, so we want low
3195 * locking overhead. 3152 * locking overhead.
3196 */ 3153 */
3197 bcm43xx_lock_irqsafe(bcm, flags); 3154 mutex_lock(&bcm->mutex);
3155 spin_lock_irqsave(&bcm->irq_lock, flags);
3198 } 3156 }
3199 3157
3200 do_periodic_work(bcm); 3158 do_periodic_work(bcm);
3201 3159
3202 if (badness > BADNESS_LIMIT) { 3160 if (badness > BADNESS_LIMIT) {
3203 bcm43xx_lock_irqonly(bcm, flags); 3161 spin_lock_irqsave(&bcm->irq_lock, flags);
3204 if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) { 3162 if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
3205 tasklet_enable(&bcm->isr_tasklet); 3163 tasklet_enable(&bcm->isr_tasklet);
3206 bcm43xx_interrupt_enable(bcm, savedirqs); 3164 bcm43xx_interrupt_enable(bcm, savedirqs);
3207 if (bcm43xx_using_pio(bcm)) 3165 if (bcm43xx_using_pio(bcm))
3208 bcm43xx_pio_thaw_txqueues(bcm); 3166 bcm43xx_pio_thaw_txqueues(bcm);
3167 bcm43xx_mac_enable(bcm);
3209 } 3168 }
3210 netif_wake_queue(bcm->net_dev); 3169 netif_wake_queue(bcm->net_dev);
3211 mmiowb();
3212 bcm43xx_unlock_irqonly(bcm, flags);
3213 bcm43xx_unlock_noirq(bcm);
3214 } else {
3215 mmiowb();
3216 bcm43xx_unlock_irqsafe(bcm, flags);
3217 } 3170 }
3171 mmiowb();
3172 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3173 mutex_unlock(&bcm->mutex);
3218} 3174}
3219 3175
3220static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) 3176static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
@@ -3243,9 +3199,9 @@ static int bcm43xx_rng_read(struct hwrng *rng, u32 *data)
3243 struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv; 3199 struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv;
3244 unsigned long flags; 3200 unsigned long flags;
3245 3201
3246 bcm43xx_lock_irqonly(bcm, flags); 3202 spin_lock_irqsave(&(bcm)->irq_lock, flags);
3247 *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG); 3203 *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG);
3248 bcm43xx_unlock_irqonly(bcm, flags); 3204 spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
3249 3205
3250 return (sizeof(u16)); 3206 return (sizeof(u16));
3251} 3207}
@@ -3271,139 +3227,322 @@ static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
3271 return err; 3227 return err;
3272} 3228}
3273 3229
3274/* This is the opposite of bcm43xx_init_board() */ 3230static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
3275static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3276{ 3231{
3232 int ret = 0;
3277 int i, err; 3233 int i, err;
3234 struct bcm43xx_coreinfo *core;
3278 3235
3279 bcm43xx_lock_noirq(bcm); 3236 bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
3237 for (i = 0; i < bcm->nr_80211_available; i++) {
3238 core = &(bcm->core_80211[i]);
3239 assert(core->available);
3240 if (!core->initialized)
3241 continue;
3242 err = bcm43xx_switch_core(bcm, core);
3243 if (err) {
3244 dprintk(KERN_ERR PFX "shutdown_all_wireless_cores "
3245 "switch_core failed (%d)\n", err);
3246 ret = err;
3247 continue;
3248 }
3249 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3250 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
3251 bcm43xx_wireless_core_cleanup(bcm);
3252 if (core == bcm->active_80211_core)
3253 bcm->active_80211_core = NULL;
3254 }
3255 free_irq(bcm->irq, bcm);
3256 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
3257
3258 return ret;
3259}
3260
3261/* This is the opposite of bcm43xx_init_board() */
3262static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3263{
3280 bcm43xx_sysfs_unregister(bcm); 3264 bcm43xx_sysfs_unregister(bcm);
3281 bcm43xx_periodic_tasks_delete(bcm); 3265 bcm43xx_periodic_tasks_delete(bcm);
3282 3266
3283 bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); 3267 mutex_lock(&(bcm)->mutex);
3268 bcm43xx_shutdown_all_wireless_cores(bcm);
3269 bcm43xx_pctl_set_crystal(bcm, 0);
3270 mutex_unlock(&(bcm)->mutex);
3271}
3272
3273static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy)
3274{
3275 phy->antenna_diversity = 0xFFFF;
3276 memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
3277 memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
3278
3279 /* Flags */
3280 phy->calibrated = 0;
3281 phy->is_locked = 0;
3282
3283 if (phy->_lo_pairs) {
3284 memset(phy->_lo_pairs, 0,
3285 sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT);
3286 }
3287 memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain));
3288}
3289
3290static void prepare_radiodata_for_init(struct bcm43xx_private *bcm,
3291 struct bcm43xx_radioinfo *radio)
3292{
3293 int i;
3294
3295 /* Set default attenuation values. */
3296 radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
3297 radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
3298 radio->txctl1 = bcm43xx_default_txctl1(bcm);
3299 radio->txctl2 = 0xFFFF;
3300 radio->txpwr_offset = 0;
3301
3302 /* NRSSI */
3303 radio->nrssislope = 0;
3304 for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++)
3305 radio->nrssi[i] = -1000;
3306 for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++)
3307 radio->nrssi_lt[i] = i;
3308
3309 radio->lofcal = 0xFFFF;
3310 radio->initval = 0xFFFF;
3311
3312 radio->aci_enable = 0;
3313 radio->aci_wlan_automatic = 0;
3314 radio->aci_hw_rssi = 0;
3315}
3316
3317static void prepare_priv_for_init(struct bcm43xx_private *bcm)
3318{
3319 int i;
3320 struct bcm43xx_coreinfo *core;
3321 struct bcm43xx_coreinfo_80211 *wlext;
3284 3322
3285 bcm43xx_rng_exit(bcm); 3323 assert(!bcm->active_80211_core);
3324
3325 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
3326
3327 /* Flags */
3328 bcm->was_initialized = 0;
3329 bcm->reg124_set_0x4 = 0;
3330
3331 /* Stats */
3332 memset(&bcm->stats, 0, sizeof(bcm->stats));
3333
3334 /* Wireless core data */
3286 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { 3335 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3287 if (!bcm->core_80211[i].available) 3336 core = &(bcm->core_80211[i]);
3288 continue; 3337 wlext = core->priv;
3289 if (!bcm->core_80211[i].initialized) 3338
3339 if (!core->available)
3290 continue; 3340 continue;
3341 assert(wlext == &(bcm->core_80211_ext[i]));
3291 3342
3292 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); 3343 prepare_phydata_for_init(&wlext->phy);
3293 assert(err == 0); 3344 prepare_radiodata_for_init(bcm, &wlext->radio);
3294 bcm43xx_wireless_core_cleanup(bcm);
3295 } 3345 }
3296 3346
3297 bcm43xx_pctl_set_crystal(bcm, 0); 3347 /* IRQ related flags */
3348 bcm->irq_reason = 0;
3349 memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason));
3350 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
3298 3351
3299 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); 3352 /* Noise calculation context */
3300 bcm43xx_unlock_noirq(bcm); 3353 memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc));
3354
3355 /* Periodic work context */
3356 bcm->periodic_state = 0;
3301} 3357}
3302 3358
3303static int bcm43xx_init_board(struct bcm43xx_private *bcm) 3359static int wireless_core_up(struct bcm43xx_private *bcm,
3360 int active_wlcore)
3361{
3362 int err;
3363
3364 if (!bcm43xx_core_enabled(bcm))
3365 bcm43xx_wireless_core_reset(bcm, 1);
3366 if (!active_wlcore)
3367 bcm43xx_wireless_core_mark_inactive(bcm);
3368 err = bcm43xx_wireless_core_init(bcm, active_wlcore);
3369 if (err)
3370 goto out;
3371 if (!active_wlcore)
3372 bcm43xx_radio_turn_off(bcm);
3373out:
3374 return err;
3375}
3376
3377/* Select and enable the "to be used" wireless core.
3378 * Locking: bcm->mutex must be aquired before calling this.
3379 * bcm->irq_lock must not be aquired.
3380 */
3381int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
3382 int phytype)
3304{ 3383{
3305 int i, err; 3384 int i, err;
3306 int connect_phy; 3385 struct bcm43xx_coreinfo *active_core = NULL;
3386 struct bcm43xx_coreinfo_80211 *active_wlext = NULL;
3387 struct bcm43xx_coreinfo *core;
3388 struct bcm43xx_coreinfo_80211 *wlext;
3389 int adjust_active_sbtmstatelow = 0;
3307 3390
3308 might_sleep(); 3391 might_sleep();
3309 3392
3310 bcm43xx_lock_noirq(bcm); 3393 if (phytype < 0) {
3311 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); 3394 /* If no phytype is requested, select the first core. */
3395 assert(bcm->core_80211[0].available);
3396 wlext = bcm->core_80211[0].priv;
3397 phytype = wlext->phy.type;
3398 }
3399 /* Find the requested core. */
3400 for (i = 0; i < bcm->nr_80211_available; i++) {
3401 core = &(bcm->core_80211[i]);
3402 wlext = core->priv;
3403 if (wlext->phy.type == phytype) {
3404 active_core = core;
3405 active_wlext = wlext;
3406 break;
3407 }
3408 }
3409 if (!active_core)
3410 return -ESRCH; /* No such PHYTYPE on this board. */
3411
3412 if (bcm->active_80211_core) {
3413 /* We already selected a wl core in the past.
3414 * So first clean up everything.
3415 */
3416 dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n");
3417 ieee80211softmac_stop(bcm->net_dev);
3418 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
3419 err = bcm43xx_disable_interrupts_sync(bcm);
3420 assert(!err);
3421 tasklet_enable(&bcm->isr_tasklet);
3422 err = bcm43xx_shutdown_all_wireless_cores(bcm);
3423 if (err)
3424 goto error;
3425 /* Ok, everything down, continue to re-initialize. */
3426 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
3427 }
3428
3429 /* Reset all data structures. */
3430 prepare_priv_for_init(bcm);
3312 3431
3313 err = bcm43xx_pctl_set_crystal(bcm, 1);
3314 if (err)
3315 goto out;
3316 err = bcm43xx_pctl_init(bcm);
3317 if (err)
3318 goto err_crystal_off;
3319 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST); 3432 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
3320 if (err) 3433 if (err)
3321 goto err_crystal_off; 3434 goto error;
3322 3435
3323 tasklet_enable(&bcm->isr_tasklet); 3436 /* Mark all unused cores "inactive". */
3324 for (i = 0; i < bcm->nr_80211_available; i++) { 3437 for (i = 0; i < bcm->nr_80211_available; i++) {
3325 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); 3438 core = &(bcm->core_80211[i]);
3326 assert(err != -ENODEV); 3439 wlext = core->priv;
3327 if (err)
3328 goto err_80211_unwind;
3329 3440
3330 /* Enable the selected wireless core. 3441 if (core == active_core)
3331 * Connect PHY only on the first core. 3442 continue;
3332 */ 3443 err = bcm43xx_switch_core(bcm, core);
3333 if (!bcm43xx_core_enabled(bcm)) { 3444 if (err) {
3334 if (bcm->nr_80211_available == 1) { 3445 dprintk(KERN_ERR PFX "Could not switch to inactive "
3335 connect_phy = bcm43xx_current_phy(bcm)->connected; 3446 "802.11 core (%d)\n", err);
3336 } else { 3447 goto error;
3337 if (i == 0)
3338 connect_phy = 1;
3339 else
3340 connect_phy = 0;
3341 }
3342 bcm43xx_wireless_core_reset(bcm, connect_phy);
3343 } 3448 }
3449 err = wireless_core_up(bcm, 0);
3450 if (err) {
3451 dprintk(KERN_ERR PFX "core_up for inactive 802.11 core "
3452 "failed (%d)\n", err);
3453 goto error;
3454 }
3455 adjust_active_sbtmstatelow = 1;
3456 }
3344 3457
3345 if (i != 0) 3458 /* Now initialize the active 802.11 core. */
3346 bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]); 3459 err = bcm43xx_switch_core(bcm, active_core);
3347 3460 if (err) {
3348 err = bcm43xx_wireless_core_init(bcm); 3461 dprintk(KERN_ERR PFX "Could not switch to active "
3349 if (err) 3462 "802.11 core (%d)\n", err);
3350 goto err_80211_unwind; 3463 goto error;
3464 }
3465 if (adjust_active_sbtmstatelow &&
3466 active_wlext->phy.type == BCM43xx_PHYTYPE_G) {
3467 u32 sbtmstatelow;
3351 3468
3352 if (i != 0) { 3469 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
3353 bcm43xx_mac_suspend(bcm); 3470 sbtmstatelow |= 0x20000000;
3354 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 3471 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
3355 bcm43xx_radio_turn_off(bcm);
3356 }
3357 } 3472 }
3358 bcm->active_80211_core = &bcm->core_80211[0]; 3473 err = wireless_core_up(bcm, 1);
3359 if (bcm->nr_80211_available >= 2) { 3474 if (err) {
3360 bcm43xx_switch_core(bcm, &bcm->core_80211[0]); 3475 dprintk(KERN_ERR PFX "core_up for active 802.11 core "
3361 bcm43xx_mac_enable(bcm); 3476 "failed (%d)\n", err);
3477 goto error;
3362 } 3478 }
3363 err = bcm43xx_rng_init(bcm); 3479 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
3364 if (err) 3480 if (err)
3365 goto err_80211_unwind; 3481 goto error;
3482 bcm->active_80211_core = active_core;
3483
3366 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); 3484 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
3367 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); 3485 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
3368 dprintk(KERN_INFO PFX "80211 cores initialized\n");
3369 bcm43xx_security_init(bcm); 3486 bcm43xx_security_init(bcm);
3370 bcm43xx_softmac_init(bcm); 3487 ieee80211softmac_start(bcm->net_dev);
3371 3488
3372 bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); 3489 /* Let's go! Be careful after enabling the IRQs.
3490 * Don't switch cores, for example.
3491 */
3492 bcm43xx_mac_enable(bcm);
3493 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
3494 err = bcm43xx_initialize_irq(bcm);
3495 if (err)
3496 goto error;
3497 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
3373 3498
3374 if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) { 3499 dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n",
3375 bcm43xx_mac_suspend(bcm); 3500 active_wlext->phy.type);
3376 bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0);
3377 bcm43xx_mac_enable(bcm);
3378 }
3379 3501
3380 /* Initialization of the board is done. Flag it as such. */ 3502 return 0;
3381 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); 3503
3504error:
3505 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
3506 bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
3507 return err;
3508}
3509
3510static int bcm43xx_init_board(struct bcm43xx_private *bcm)
3511{
3512 int err;
3513
3514 mutex_lock(&(bcm)->mutex);
3515
3516 tasklet_enable(&bcm->isr_tasklet);
3517 err = bcm43xx_pctl_set_crystal(bcm, 1);
3518 if (err)
3519 goto err_tasklet;
3520 err = bcm43xx_pctl_init(bcm);
3521 if (err)
3522 goto err_crystal_off;
3523 err = bcm43xx_select_wireless_core(bcm, -1);
3524 if (err)
3525 goto err_crystal_off;
3382 3526
3383 bcm43xx_periodic_tasks_setup(bcm); 3527 bcm43xx_periodic_tasks_setup(bcm);
3384 bcm43xx_sysfs_register(bcm); 3528 err = bcm43xx_sysfs_register(bcm);
3385 //FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though... 3529 if (err)
3530 goto err_wlshutdown;
3386 3531
3387 /*FIXME: This should be handled by softmac instead. */ 3532 /*FIXME: This should be handled by softmac instead. */
3388 schedule_work(&bcm->softmac->associnfo.work); 3533 schedule_work(&bcm->softmac->associnfo.work);
3389 3534
3390 assert(err == 0);
3391out: 3535out:
3392 bcm43xx_unlock_noirq(bcm); 3536 mutex_unlock(&(bcm)->mutex);
3393 3537
3394 return err; 3538 return err;
3395 3539
3396err_80211_unwind: 3540err_wlshutdown:
3397 tasklet_disable(&bcm->isr_tasklet); 3541 bcm43xx_shutdown_all_wireless_cores(bcm);
3398 /* unwind all 80211 initialization */
3399 for (i = 0; i < bcm->nr_80211_available; i++) {
3400 if (!bcm->core_80211[i].initialized)
3401 continue;
3402 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3403 bcm43xx_wireless_core_cleanup(bcm);
3404 }
3405err_crystal_off: 3542err_crystal_off:
3406 bcm43xx_pctl_set_crystal(bcm, 0); 3543 bcm43xx_pctl_set_crystal(bcm, 0);
3544err_tasklet:
3545 tasklet_disable(&bcm->isr_tasklet);
3407 goto out; 3546 goto out;
3408} 3547}
3409 3548
@@ -3647,7 +3786,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
3647 struct bcm43xx_radioinfo *radio; 3786 struct bcm43xx_radioinfo *radio;
3648 unsigned long flags; 3787 unsigned long flags;
3649 3788
3650 bcm43xx_lock_irqsafe(bcm, flags); 3789 mutex_lock(&bcm->mutex);
3790 spin_lock_irqsave(&bcm->irq_lock, flags);
3651 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { 3791 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
3652 bcm43xx_mac_suspend(bcm); 3792 bcm43xx_mac_suspend(bcm);
3653 bcm43xx_radio_selectchannel(bcm, channel, 0); 3793 bcm43xx_radio_selectchannel(bcm, channel, 0);
@@ -3656,7 +3796,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
3656 radio = bcm43xx_current_radio(bcm); 3796 radio = bcm43xx_current_radio(bcm);
3657 radio->initial_channel = channel; 3797 radio->initial_channel = channel;
3658 } 3798 }
3659 bcm43xx_unlock_irqsafe(bcm, flags); 3799 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3800 mutex_unlock(&bcm->mutex);
3660} 3801}
3661 3802
3662/* set_security() callback in struct ieee80211_device */ 3803/* set_security() callback in struct ieee80211_device */
@@ -3670,7 +3811,8 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
3670 3811
3671 dprintk(KERN_INFO PFX "set security called"); 3812 dprintk(KERN_INFO PFX "set security called");
3672 3813
3673 bcm43xx_lock_irqsafe(bcm, flags); 3814 mutex_lock(&bcm->mutex);
3815 spin_lock_irqsave(&bcm->irq_lock, flags);
3674 3816
3675 for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) 3817 for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
3676 if (sec->flags & (1<<keyidx)) { 3818 if (sec->flags & (1<<keyidx)) {
@@ -3739,7 +3881,8 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
3739 } else 3881 } else
3740 bcm43xx_clear_keys(bcm); 3882 bcm43xx_clear_keys(bcm);
3741 } 3883 }
3742 bcm43xx_unlock_irqsafe(bcm, flags); 3884 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3885 mutex_unlock(&bcm->mutex);
3743} 3886}
3744 3887
3745/* hard_start_xmit() callback in struct ieee80211_device */ 3888/* hard_start_xmit() callback in struct ieee80211_device */
@@ -3751,10 +3894,10 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
3751 int err = -ENODEV; 3894 int err = -ENODEV;
3752 unsigned long flags; 3895 unsigned long flags;
3753 3896
3754 bcm43xx_lock_irqonly(bcm, flags); 3897 spin_lock_irqsave(&bcm->irq_lock, flags);
3755 if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) 3898 if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
3756 err = bcm43xx_tx(bcm, txb); 3899 err = bcm43xx_tx(bcm, txb);
3757 bcm43xx_unlock_irqonly(bcm, flags); 3900 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3758 3901
3759 return err; 3902 return err;
3760} 3903}
@@ -3769,9 +3912,9 @@ static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
3769 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 3912 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3770 unsigned long flags; 3913 unsigned long flags;
3771 3914
3772 bcm43xx_lock_irqonly(bcm, flags); 3915 spin_lock_irqsave(&bcm->irq_lock, flags);
3773 bcm43xx_controller_restart(bcm, "TX timeout"); 3916 bcm43xx_controller_restart(bcm, "TX timeout");
3774 bcm43xx_unlock_irqonly(bcm, flags); 3917 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3775} 3918}
3776 3919
3777#ifdef CONFIG_NET_POLL_CONTROLLER 3920#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3781,7 +3924,8 @@ static void bcm43xx_net_poll_controller(struct net_device *net_dev)
3781 unsigned long flags; 3924 unsigned long flags;
3782 3925
3783 local_irq_save(flags); 3926 local_irq_save(flags);
3784 bcm43xx_interrupt_handler(bcm->irq, bcm, NULL); 3927 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
3928 bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
3785 local_irq_restore(flags); 3929 local_irq_restore(flags);
3786} 3930}
3787#endif /* CONFIG_NET_POLL_CONTROLLER */ 3931#endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -3799,7 +3943,7 @@ static int bcm43xx_net_stop(struct net_device *net_dev)
3799 int err; 3943 int err;
3800 3944
3801 ieee80211softmac_stop(net_dev); 3945 ieee80211softmac_stop(net_dev);
3802 err = bcm43xx_disable_interrupts_sync(bcm, NULL); 3946 err = bcm43xx_disable_interrupts_sync(bcm);
3803 assert(!err); 3947 assert(!err);
3804 bcm43xx_free_board(bcm); 3948 bcm43xx_free_board(bcm);
3805 3949
@@ -3818,10 +3962,12 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
3818 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; 3962 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
3819 3963
3820 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; 3964 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
3965 bcm->mac_suspended = 1;
3821 bcm->pci_dev = pci_dev; 3966 bcm->pci_dev = pci_dev;
3822 bcm->net_dev = net_dev; 3967 bcm->net_dev = net_dev;
3823 bcm->bad_frames_preempt = modparam_bad_frames_preempt; 3968 bcm->bad_frames_preempt = modparam_bad_frames_preempt;
3824 spin_lock_init(&bcm->irq_lock); 3969 spin_lock_init(&bcm->irq_lock);
3970 spin_lock_init(&bcm->leds_lock);
3825 mutex_init(&bcm->mutex); 3971 mutex_init(&bcm->mutex);
3826 tasklet_init(&bcm->isr_tasklet, 3972 tasklet_init(&bcm->isr_tasklet,
3827 (void (*)(unsigned long))bcm43xx_interrupt_tasklet, 3973 (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
@@ -3940,7 +4086,6 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
3940 bcm43xx_debugfs_remove_device(bcm); 4086 bcm43xx_debugfs_remove_device(bcm);
3941 unregister_netdev(net_dev); 4087 unregister_netdev(net_dev);
3942 bcm43xx_detach_board(bcm); 4088 bcm43xx_detach_board(bcm);
3943 assert(bcm->ucode == NULL);
3944 free_ieee80211softmac(net_dev); 4089 free_ieee80211softmac(net_dev);
3945} 4090}
3946 4091
@@ -3950,47 +4095,25 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
3950static void bcm43xx_chip_reset(void *_bcm) 4095static void bcm43xx_chip_reset(void *_bcm)
3951{ 4096{
3952 struct bcm43xx_private *bcm = _bcm; 4097 struct bcm43xx_private *bcm = _bcm;
3953 struct net_device *net_dev = bcm->net_dev; 4098 struct bcm43xx_phyinfo *phy;
3954 struct pci_dev *pci_dev = bcm->pci_dev;
3955 int err; 4099 int err;
3956 int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
3957 4100
3958 netif_stop_queue(bcm->net_dev); 4101 mutex_lock(&(bcm)->mutex);
3959 tasklet_disable(&bcm->isr_tasklet); 4102 phy = bcm43xx_current_phy(bcm);
4103 err = bcm43xx_select_wireless_core(bcm, phy->type);
4104 mutex_unlock(&(bcm)->mutex);
3960 4105
3961 bcm->firmware_norelease = 1; 4106 printk(KERN_ERR PFX "Controller restart%s\n",
3962 if (was_initialized) 4107 (err == 0) ? "ed" : " failed");
3963 bcm43xx_free_board(bcm);
3964 bcm->firmware_norelease = 0;
3965 bcm43xx_detach_board(bcm);
3966 err = bcm43xx_init_private(bcm, net_dev, pci_dev);
3967 if (err)
3968 goto failure;
3969 err = bcm43xx_attach_board(bcm);
3970 if (err)
3971 goto failure;
3972 if (was_initialized) {
3973 err = bcm43xx_init_board(bcm);
3974 if (err)
3975 goto failure;
3976 }
3977 netif_wake_queue(bcm->net_dev);
3978 printk(KERN_INFO PFX "Controller restarted\n");
3979
3980 return;
3981failure:
3982 printk(KERN_ERR PFX "Controller restart failed\n");
3983} 4108}
3984 4109
3985/* Hard-reset the chip. 4110/* Hard-reset the chip.
3986 * This can be called from interrupt or process context. 4111 * This can be called from interrupt or process context.
3987 * Make sure to _not_ re-enable device interrupts after this has been called. 4112 */
3988*/
3989void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) 4113void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
3990{ 4114{
4115 assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
3991 bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING); 4116 bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING);
3992 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3993 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
3994 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); 4117 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
3995 INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); 4118 INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
3996 schedule_work(&bcm->restart_work); 4119 schedule_work(&bcm->restart_work);
@@ -4002,21 +4125,16 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
4002{ 4125{
4003 struct net_device *net_dev = pci_get_drvdata(pdev); 4126 struct net_device *net_dev = pci_get_drvdata(pdev);
4004 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 4127 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4005 unsigned long flags; 4128 int err;
4006 int try_to_shutdown = 0, err;
4007 4129
4008 dprintk(KERN_INFO PFX "Suspending...\n"); 4130 dprintk(KERN_INFO PFX "Suspending...\n");
4009 4131
4010 bcm43xx_lock_irqsafe(bcm, flags);
4011 bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
4012 if (bcm->was_initialized)
4013 try_to_shutdown = 1;
4014 bcm43xx_unlock_irqsafe(bcm, flags);
4015
4016 netif_device_detach(net_dev); 4132 netif_device_detach(net_dev);
4017 if (try_to_shutdown) { 4133 bcm->was_initialized = 0;
4134 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
4135 bcm->was_initialized = 1;
4018 ieee80211softmac_stop(net_dev); 4136 ieee80211softmac_stop(net_dev);
4019 err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate); 4137 err = bcm43xx_disable_interrupts_sync(bcm);
4020 if (unlikely(err)) { 4138 if (unlikely(err)) {
4021 dprintk(KERN_ERR PFX "Suspend failed.\n"); 4139 dprintk(KERN_ERR PFX "Suspend failed.\n");
4022 return -EAGAIN; 4140 return -EAGAIN;
@@ -4049,17 +4167,14 @@ static int bcm43xx_resume(struct pci_dev *pdev)
4049 pci_restore_state(pdev); 4167 pci_restore_state(pdev);
4050 4168
4051 bcm43xx_chipset_attach(bcm); 4169 bcm43xx_chipset_attach(bcm);
4052 if (bcm->was_initialized) { 4170 if (bcm->was_initialized)
4053 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
4054 err = bcm43xx_init_board(bcm); 4171 err = bcm43xx_init_board(bcm);
4055 }
4056 if (err) { 4172 if (err) {
4057 printk(KERN_ERR PFX "Resume failed!\n"); 4173 printk(KERN_ERR PFX "Resume failed!\n");
4058 return err; 4174 return err;
4059 } 4175 }
4060
4061 netif_device_attach(net_dev); 4176 netif_device_attach(net_dev);
4062 4177
4063 dprintk(KERN_INFO PFX "Device resumed.\n"); 4178 dprintk(KERN_INFO PFX "Device resumed.\n");
4064 4179
4065 return 0; 4180 return 0;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
index 116493671f88..505c86e2007a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
@@ -133,6 +133,9 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
133 133
134int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core); 134int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
135 135
136int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
137 int phytype);
138
136void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); 139void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
137 140
138void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); 141void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index f8200deecc8a..eafd0f662686 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -81,6 +81,16 @@ static const s8 bcm43xx_tssi2dbm_g_table[] = {
81static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); 81static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
82 82
83 83
84static inline
85void bcm43xx_voluntary_preempt(void)
86{
87 assert(!in_atomic() && !in_irq() &&
88 !in_interrupt() && !irqs_disabled());
89#ifndef CONFIG_PREEMPT
90 cond_resched();
91#endif /* CONFIG_PREEMPT */
92}
93
84void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) 94void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
85{ 95{
86 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 96 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
@@ -133,22 +143,14 @@ void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
133void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) 143void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
134{ 144{
135 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 145 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
136 unsigned long flags;
137 146
138 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ 147 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
139 if (phy->calibrated) 148 if (phy->calibrated)
140 return; 149 return;
141 if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) { 150 if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
142 /* We do not want to be preempted while calibrating
143 * the hardware.
144 */
145 local_irq_save(flags);
146
147 bcm43xx_wireless_core_reset(bcm, 0); 151 bcm43xx_wireless_core_reset(bcm, 0);
148 bcm43xx_phy_initg(bcm); 152 bcm43xx_phy_initg(bcm);
149 bcm43xx_wireless_core_reset(bcm, 1); 153 bcm43xx_wireless_core_reset(bcm, 1);
150
151 local_irq_restore(flags);
152 } 154 }
153 phy->calibrated = 1; 155 phy->calibrated = 1;
154} 156}
@@ -1299,7 +1301,9 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
1299{ 1301{
1300 int i; 1302 int i;
1301 u16 ret = 0; 1303 u16 ret = 0;
1304 unsigned long flags;
1302 1305
1306 local_irq_save(flags);
1303 for (i = 0; i < 10; i++){ 1307 for (i = 0; i < 10; i++){
1304 bcm43xx_phy_write(bcm, 0x0015, 0xAFA0); 1308 bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
1305 udelay(1); 1309 udelay(1);
@@ -1309,6 +1313,8 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
1309 udelay(40); 1313 udelay(40);
1310 ret += bcm43xx_phy_read(bcm, 0x002C); 1314 ret += bcm43xx_phy_read(bcm, 0x002C);
1311 } 1315 }
1316 local_irq_restore(flags);
1317 bcm43xx_voluntary_preempt();
1312 1318
1313 return ret; 1319 return ret;
1314} 1320}
@@ -1435,6 +1441,7 @@ u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
1435 } 1441 }
1436 ret = bcm43xx_phy_read(bcm, 0x002D); 1442 ret = bcm43xx_phy_read(bcm, 0x002D);
1437 local_irq_restore(flags); 1443 local_irq_restore(flags);
1444 bcm43xx_voluntary_preempt();
1438 1445
1439 return ret; 1446 return ret;
1440} 1447}
@@ -1760,6 +1767,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
1760 bcm43xx_radio_write16(bcm, 0x43, i); 1767 bcm43xx_radio_write16(bcm, 0x43, i);
1761 bcm43xx_radio_write16(bcm, 0x52, radio->txctl2); 1768 bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
1762 udelay(10); 1769 udelay(10);
1770 bcm43xx_voluntary_preempt();
1763 1771
1764 bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); 1772 bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
1765 1773
@@ -1803,6 +1811,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
1803 radio->txctl2 1811 radio->txctl2
1804 | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? 1812 | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
1805 udelay(10); 1813 udelay(10);
1814 bcm43xx_voluntary_preempt();
1806 1815
1807 bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); 1816 bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
1808 1817
@@ -1824,6 +1833,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
1824 bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2); 1833 bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
1825 udelay(2); 1834 udelay(2);
1826 bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3); 1835 bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
1836 bcm43xx_voluntary_preempt();
1827 } else 1837 } else
1828 bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0); 1838 bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
1829 bcm43xx_phy_lo_adjust(bcm, is_initializing); 1839 bcm43xx_phy_lo_adjust(bcm, is_initializing);
@@ -2188,12 +2198,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm)
2188{ 2198{
2189 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 2199 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2190 int err = -ENODEV; 2200 int err = -ENODEV;
2191 unsigned long flags;
2192
2193 /* We do not want to be preempted while calibrating
2194 * the hardware.
2195 */
2196 local_irq_save(flags);
2197 2201
2198 switch (phy->type) { 2202 switch (phy->type) {
2199 case BCM43xx_PHYTYPE_A: 2203 case BCM43xx_PHYTYPE_A:
@@ -2227,7 +2231,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm)
2227 err = 0; 2231 err = 0;
2228 break; 2232 break;
2229 } 2233 }
2230 local_irq_restore(flags);
2231 if (err) 2234 if (err)
2232 printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n"); 2235 printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
2233 2236
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
index 574085c46152..c60c1743ea06 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -262,7 +262,7 @@ static void tx_tasklet(unsigned long d)
262 int err; 262 int err;
263 u16 txctl; 263 u16 txctl;
264 264
265 bcm43xx_lock_irqonly(bcm, flags); 265 spin_lock_irqsave(&bcm->irq_lock, flags);
266 266
267 if (queue->tx_frozen) 267 if (queue->tx_frozen)
268 goto out_unlock; 268 goto out_unlock;
@@ -300,7 +300,7 @@ static void tx_tasklet(unsigned long d)
300 continue; 300 continue;
301 } 301 }
302out_unlock: 302out_unlock:
303 bcm43xx_unlock_irqonly(bcm, flags); 303 spin_unlock_irqrestore(&bcm->irq_lock, flags);
304} 304}
305 305
306static void setup_txqueues(struct bcm43xx_pioqueue *queue) 306static void setup_txqueues(struct bcm43xx_pioqueue *queue)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
index 6a23bdc75412..ece335178f6a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -120,12 +120,14 @@ 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_irqsafe(bcm, flags); 123 mutex_lock(&bcm->mutex);
124 spin_lock_irqsave(&bcm->irq_lock, flags);
124 err = bcm43xx_sprom_read(bcm, sprom); 125 err = bcm43xx_sprom_read(bcm, sprom);
125 if (!err) 126 if (!err)
126 err = sprom2hex(sprom, buf, PAGE_SIZE); 127 err = sprom2hex(sprom, buf, PAGE_SIZE);
127 mmiowb(); 128 mmiowb();
128 bcm43xx_unlock_irqsafe(bcm, flags); 129 spin_unlock_irqrestore(&bcm->irq_lock, flags);
130 mutex_unlock(&bcm->mutex);
129 kfree(sprom); 131 kfree(sprom);
130 132
131 return err; 133 return err;
@@ -150,10 +152,14 @@ static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
150 err = hex2sprom(sprom, buf, count); 152 err = hex2sprom(sprom, buf, count);
151 if (err) 153 if (err)
152 goto out_kfree; 154 goto out_kfree;
153 bcm43xx_lock_irqsafe(bcm, flags); 155 mutex_lock(&bcm->mutex);
156 spin_lock_irqsave(&bcm->irq_lock, flags);
157 spin_lock(&bcm->leds_lock);
154 err = bcm43xx_sprom_write(bcm, sprom); 158 err = bcm43xx_sprom_write(bcm, sprom);
155 mmiowb(); 159 mmiowb();
156 bcm43xx_unlock_irqsafe(bcm, flags); 160 spin_unlock(&bcm->leds_lock);
161 spin_unlock_irqrestore(&bcm->irq_lock, flags);
162 mutex_unlock(&bcm->mutex);
157out_kfree: 163out_kfree:
158 kfree(sprom); 164 kfree(sprom);
159 165
@@ -176,7 +182,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
176 if (!capable(CAP_NET_ADMIN)) 182 if (!capable(CAP_NET_ADMIN))
177 return -EPERM; 183 return -EPERM;
178 184
179 bcm43xx_lock_noirq(bcm); 185 mutex_lock(&bcm->mutex);
180 186
181 switch (bcm43xx_current_radio(bcm)->interfmode) { 187 switch (bcm43xx_current_radio(bcm)->interfmode) {
182 case BCM43xx_RADIO_INTERFMODE_NONE: 188 case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -193,7 +199,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
193 } 199 }
194 err = 0; 200 err = 0;
195 201
196 bcm43xx_unlock_noirq(bcm); 202 mutex_unlock(&bcm->mutex);
197 203
198 return err ? err : count; 204 return err ? err : count;
199 205
@@ -229,7 +235,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
229 return -EINVAL; 235 return -EINVAL;
230 } 236 }
231 237
232 bcm43xx_lock_irqsafe(bcm, flags); 238 mutex_lock(&bcm->mutex);
239 spin_lock_irqsave(&bcm->irq_lock, flags);
233 240
234 err = bcm43xx_radio_set_interference_mitigation(bcm, mode); 241 err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
235 if (err) { 242 if (err) {
@@ -237,7 +244,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
237 "supported by device\n"); 244 "supported by device\n");
238 } 245 }
239 mmiowb(); 246 mmiowb();
240 bcm43xx_unlock_irqsafe(bcm, flags); 247 spin_unlock_irqrestore(&bcm->irq_lock, flags);
248 mutex_unlock(&bcm->mutex);
241 249
242 return err ? err : count; 250 return err ? err : count;
243} 251}
@@ -257,7 +265,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
257 if (!capable(CAP_NET_ADMIN)) 265 if (!capable(CAP_NET_ADMIN))
258 return -EPERM; 266 return -EPERM;
259 267
260 bcm43xx_lock_noirq(bcm); 268 mutex_lock(&bcm->mutex);
261 269
262 if (bcm->short_preamble) 270 if (bcm->short_preamble)
263 count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); 271 count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
@@ -265,7 +273,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
265 count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); 273 count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
266 274
267 err = 0; 275 err = 0;
268 bcm43xx_unlock_noirq(bcm); 276 mutex_unlock(&bcm->mutex);
269 277
270 return err ? err : count; 278 return err ? err : count;
271} 279}
@@ -285,12 +293,14 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
285 value = get_boolean(buf, count); 293 value = get_boolean(buf, count);
286 if (value < 0) 294 if (value < 0)
287 return value; 295 return value;
288 bcm43xx_lock_irqsafe(bcm, flags); 296 mutex_lock(&bcm->mutex);
297 spin_lock_irqsave(&bcm->irq_lock, flags);
289 298
290 bcm->short_preamble = !!value; 299 bcm->short_preamble = !!value;
291 300
292 err = 0; 301 err = 0;
293 bcm43xx_unlock_irqsafe(bcm, flags); 302 spin_unlock_irqrestore(&bcm->irq_lock, flags);
303 mutex_unlock(&bcm->mutex);
294 304
295 return err ? err : count; 305 return err ? err : count;
296} 306}
@@ -299,6 +309,70 @@ static DEVICE_ATTR(shortpreamble, 0644,
299 bcm43xx_attr_preamble_show, 309 bcm43xx_attr_preamble_show,
300 bcm43xx_attr_preamble_store); 310 bcm43xx_attr_preamble_store);
301 311
312static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
313 struct device_attribute *attr,
314 const char *buf, size_t count)
315{
316 struct bcm43xx_private *bcm = dev_to_bcm(dev);
317 int phytype;
318 int err = -EINVAL;
319
320 if (count < 1)
321 goto out;
322 switch (buf[0]) {
323 case 'a': case 'A':
324 phytype = BCM43xx_PHYTYPE_A;
325 break;
326 case 'b': case 'B':
327 phytype = BCM43xx_PHYTYPE_B;
328 break;
329 case 'g': case 'G':
330 phytype = BCM43xx_PHYTYPE_G;
331 break;
332 default:
333 goto out;
334 }
335
336 mutex_lock(&(bcm)->mutex);
337 err = bcm43xx_select_wireless_core(bcm, phytype);
338 mutex_unlock(&(bcm)->mutex);
339 if (err == -ESRCH)
340 err = -ENODEV;
341
342out:
343 return err ? err : count;
344}
345
346static ssize_t bcm43xx_attr_phymode_show(struct device *dev,
347 struct device_attribute *attr,
348 char *buf)
349{
350 struct bcm43xx_private *bcm = dev_to_bcm(dev);
351 ssize_t count = 0;
352
353 mutex_lock(&(bcm)->mutex);
354 switch (bcm43xx_current_phy(bcm)->type) {
355 case BCM43xx_PHYTYPE_A:
356 snprintf(buf, PAGE_SIZE, "A");
357 break;
358 case BCM43xx_PHYTYPE_B:
359 snprintf(buf, PAGE_SIZE, "B");
360 break;
361 case BCM43xx_PHYTYPE_G:
362 snprintf(buf, PAGE_SIZE, "G");
363 break;
364 default:
365 assert(0);
366 }
367 mutex_unlock(&(bcm)->mutex);
368
369 return count;
370}
371
372static DEVICE_ATTR(phymode, 0644,
373 bcm43xx_attr_phymode_show,
374 bcm43xx_attr_phymode_store);
375
302int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) 376int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
303{ 377{
304 struct device *dev = &bcm->pci_dev->dev; 378 struct device *dev = &bcm->pci_dev->dev;
@@ -315,9 +389,14 @@ int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
315 err = device_create_file(dev, &dev_attr_shortpreamble); 389 err = device_create_file(dev, &dev_attr_shortpreamble);
316 if (err) 390 if (err)
317 goto err_remove_interfmode; 391 goto err_remove_interfmode;
392 err = device_create_file(dev, &dev_attr_phymode);
393 if (err)
394 goto err_remove_shortpreamble;
318 395
319out: 396out:
320 return err; 397 return err;
398err_remove_shortpreamble:
399 device_remove_file(dev, &dev_attr_shortpreamble);
321err_remove_interfmode: 400err_remove_interfmode:
322 device_remove_file(dev, &dev_attr_interference); 401 device_remove_file(dev, &dev_attr_interference);
323err_remove_sprom: 402err_remove_sprom:
@@ -329,6 +408,7 @@ void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
329{ 408{
330 struct device *dev = &bcm->pci_dev->dev; 409 struct device *dev = &bcm->pci_dev->dev;
331 410
411 device_remove_file(dev, &dev_attr_phymode);
332 device_remove_file(dev, &dev_attr_shortpreamble); 412 device_remove_file(dev, &dev_attr_shortpreamble);
333 device_remove_file(dev, &dev_attr_interference); 413 device_remove_file(dev, &dev_attr_interference);
334 device_remove_file(dev, &dev_attr_sprom); 414 device_remove_file(dev, &dev_attr_sprom);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index 5c36e29efff7..1d3a3aaf96ec 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -47,6 +47,8 @@
47#define BCM43xx_WX_VERSION 18 47#define BCM43xx_WX_VERSION 18
48 48
49#define MAX_WX_STRING 80 49#define MAX_WX_STRING 80
50/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
51#define RX_RSSI_MAX 60
50 52
51 53
52static int bcm43xx_wx_get_name(struct net_device *net_dev, 54static int bcm43xx_wx_get_name(struct net_device *net_dev,
@@ -56,12 +58,11 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev,
56{ 58{
57 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 59 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
58 int i; 60 int i;
59 unsigned long flags;
60 struct bcm43xx_phyinfo *phy; 61 struct bcm43xx_phyinfo *phy;
61 char suffix[7] = { 0 }; 62 char suffix[7] = { 0 };
62 int have_a = 0, have_b = 0, have_g = 0; 63 int have_a = 0, have_b = 0, have_g = 0;
63 64
64 bcm43xx_lock_irqsafe(bcm, flags); 65 mutex_lock(&bcm->mutex);
65 for (i = 0; i < bcm->nr_80211_available; i++) { 66 for (i = 0; i < bcm->nr_80211_available; i++) {
66 phy = &(bcm->core_80211_ext[i].phy); 67 phy = &(bcm->core_80211_ext[i].phy);
67 switch (phy->type) { 68 switch (phy->type) {
@@ -77,7 +78,7 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev,
77 assert(0); 78 assert(0);
78 } 79 }
79 } 80 }
80 bcm43xx_unlock_irqsafe(bcm, flags); 81 mutex_unlock(&bcm->mutex);
81 82
82 i = 0; 83 i = 0;
83 if (have_a) { 84 if (have_a) {
@@ -111,7 +112,9 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
111 int freq; 112 int freq;
112 int err = -EINVAL; 113 int err = -EINVAL;
113 114
114 bcm43xx_lock_irqsafe(bcm, flags); 115 mutex_lock(&bcm->mutex);
116 spin_lock_irqsave(&bcm->irq_lock, flags);
117
115 if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { 118 if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
116 channel = data->freq.m; 119 channel = data->freq.m;
117 freq = bcm43xx_channel_to_freq(bcm, channel); 120 freq = bcm43xx_channel_to_freq(bcm, channel);
@@ -131,7 +134,8 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
131 err = 0; 134 err = 0;
132 } 135 }
133out_unlock: 136out_unlock:
134 bcm43xx_unlock_irqsafe(bcm, flags); 137 spin_unlock_irqrestore(&bcm->irq_lock, flags);
138 mutex_unlock(&bcm->mutex);
135 139
136 return err; 140 return err;
137} 141}
@@ -143,11 +147,10 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
143{ 147{
144 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 148 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
145 struct bcm43xx_radioinfo *radio; 149 struct bcm43xx_radioinfo *radio;
146 unsigned long flags;
147 int err = -ENODEV; 150 int err = -ENODEV;
148 u16 channel; 151 u16 channel;
149 152
150 bcm43xx_lock_irqsafe(bcm, flags); 153 mutex_lock(&bcm->mutex);
151 radio = bcm43xx_current_radio(bcm); 154 radio = bcm43xx_current_radio(bcm);
152 channel = radio->channel; 155 channel = radio->channel;
153 if (channel == 0xFF) { 156 if (channel == 0xFF) {
@@ -162,7 +165,7 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
162 165
163 err = 0; 166 err = 0;
164out_unlock: 167out_unlock:
165 bcm43xx_unlock_irqsafe(bcm, flags); 168 mutex_unlock(&bcm->mutex);
166 169
167 return err; 170 return err;
168} 171}
@@ -180,13 +183,15 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev,
180 if (mode == IW_MODE_AUTO) 183 if (mode == IW_MODE_AUTO)
181 mode = BCM43xx_INITIAL_IWMODE; 184 mode = BCM43xx_INITIAL_IWMODE;
182 185
183 bcm43xx_lock_irqsafe(bcm, flags); 186 mutex_lock(&bcm->mutex);
187 spin_lock_irqsave(&bcm->irq_lock, flags);
184 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { 188 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
185 if (bcm->ieee->iw_mode != mode) 189 if (bcm->ieee->iw_mode != mode)
186 bcm43xx_set_iwmode(bcm, mode); 190 bcm43xx_set_iwmode(bcm, mode);
187 } else 191 } else
188 bcm->ieee->iw_mode = mode; 192 bcm->ieee->iw_mode = mode;
189 bcm43xx_unlock_irqsafe(bcm, flags); 193 spin_unlock_irqrestore(&bcm->irq_lock, flags);
194 mutex_unlock(&bcm->mutex);
190 195
191 return 0; 196 return 0;
192} 197}
@@ -197,11 +202,10 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev,
197 char *extra) 202 char *extra)
198{ 203{
199 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 204 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
200 unsigned long flags;
201 205
202 bcm43xx_lock_irqsafe(bcm, flags); 206 mutex_lock(&bcm->mutex);
203 data->mode = bcm->ieee->iw_mode; 207 data->mode = bcm->ieee->iw_mode;
204 bcm43xx_unlock_irqsafe(bcm, flags); 208 mutex_unlock(&bcm->mutex);
205 209
206 return 0; 210 return 0;
207} 211}
@@ -214,7 +218,6 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
214 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 218 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
215 struct iw_range *range = (struct iw_range *)extra; 219 struct iw_range *range = (struct iw_range *)extra;
216 const struct ieee80211_geo *geo; 220 const struct ieee80211_geo *geo;
217 unsigned long flags;
218 int i, j; 221 int i, j;
219 struct bcm43xx_phyinfo *phy; 222 struct bcm43xx_phyinfo *phy;
220 223
@@ -226,15 +229,14 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
226 range->throughput = 27 * 1000 * 1000; 229 range->throughput = 27 * 1000 * 1000;
227 230
228 range->max_qual.qual = 100; 231 range->max_qual.qual = 100;
229 /* TODO: Real max RSSI */ 232 range->max_qual.level = 152; /* set floor at -104 dBm (152 - 256) */
230 range->max_qual.level = 3; 233 range->max_qual.noise = 152;
231 range->max_qual.noise = 100; 234 range->max_qual.updated = IW_QUAL_ALL_UPDATED;
232 range->max_qual.updated = 7;
233 235
234 range->avg_qual.qual = 70; 236 range->avg_qual.qual = 50;
235 range->avg_qual.level = 2; 237 range->avg_qual.level = 0;
236 range->avg_qual.noise = 40; 238 range->avg_qual.noise = 0;
237 range->avg_qual.updated = 7; 239 range->avg_qual.updated = IW_QUAL_ALL_UPDATED;
238 240
239 range->min_rts = BCM43xx_MIN_RTS_THRESHOLD; 241 range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
240 range->max_rts = BCM43xx_MAX_RTS_THRESHOLD; 242 range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
@@ -254,7 +256,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
254 IW_ENC_CAPA_CIPHER_TKIP | 256 IW_ENC_CAPA_CIPHER_TKIP |
255 IW_ENC_CAPA_CIPHER_CCMP; 257 IW_ENC_CAPA_CIPHER_CCMP;
256 258
257 bcm43xx_lock_irqsafe(bcm, flags); 259 mutex_lock(&bcm->mutex);
258 phy = bcm43xx_current_phy(bcm); 260 phy = bcm43xx_current_phy(bcm);
259 261
260 range->num_bitrates = 0; 262 range->num_bitrates = 0;
@@ -301,7 +303,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
301 } 303 }
302 range->num_frequency = j; 304 range->num_frequency = j;
303 305
304 bcm43xx_unlock_irqsafe(bcm, flags); 306 mutex_unlock(&bcm->mutex);
305 307
306 return 0; 308 return 0;
307} 309}
@@ -314,11 +316,11 @@ static int bcm43xx_wx_set_nick(struct net_device *net_dev,
314 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 316 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
315 size_t len; 317 size_t len;
316 318
317 bcm43xx_lock_noirq(bcm); 319 mutex_lock(&bcm->mutex);
318 len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); 320 len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
319 memcpy(bcm->nick, extra, len); 321 memcpy(bcm->nick, extra, len);
320 bcm->nick[len] = '\0'; 322 bcm->nick[len] = '\0';
321 bcm43xx_unlock_noirq(bcm); 323 mutex_unlock(&bcm->mutex);
322 324
323 return 0; 325 return 0;
324} 326}
@@ -331,12 +333,12 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev,
331 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 333 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
332 size_t len; 334 size_t len;
333 335
334 bcm43xx_lock_noirq(bcm); 336 mutex_lock(&bcm->mutex);
335 len = strlen(bcm->nick) + 1; 337 len = strlen(bcm->nick) + 1;
336 memcpy(extra, bcm->nick, len); 338 memcpy(extra, bcm->nick, len);
337 data->data.length = (__u16)len; 339 data->data.length = (__u16)len;
338 data->data.flags = 1; 340 data->data.flags = 1;
339 bcm43xx_unlock_noirq(bcm); 341 mutex_unlock(&bcm->mutex);
340 342
341 return 0; 343 return 0;
342} 344}
@@ -350,7 +352,8 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev,
350 unsigned long flags; 352 unsigned long flags;
351 int err = -EINVAL; 353 int err = -EINVAL;
352 354
353 bcm43xx_lock_irqsafe(bcm, flags); 355 mutex_lock(&bcm->mutex);
356 spin_lock_irqsave(&bcm->irq_lock, flags);
354 if (data->rts.disabled) { 357 if (data->rts.disabled) {
355 bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; 358 bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
356 err = 0; 359 err = 0;
@@ -361,7 +364,8 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev,
361 err = 0; 364 err = 0;
362 } 365 }
363 } 366 }
364 bcm43xx_unlock_irqsafe(bcm, flags); 367 spin_unlock_irqrestore(&bcm->irq_lock, flags);
368 mutex_unlock(&bcm->mutex);
365 369
366 return err; 370 return err;
367} 371}
@@ -372,13 +376,12 @@ static int bcm43xx_wx_get_rts(struct net_device *net_dev,
372 char *extra) 376 char *extra)
373{ 377{
374 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 378 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
375 unsigned long flags;
376 379
377 bcm43xx_lock_irqsafe(bcm, flags); 380 mutex_lock(&bcm->mutex);
378 data->rts.value = bcm->rts_threshold; 381 data->rts.value = bcm->rts_threshold;
379 data->rts.fixed = 0; 382 data->rts.fixed = 0;
380 data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); 383 data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
381 bcm43xx_unlock_irqsafe(bcm, flags); 384 mutex_unlock(&bcm->mutex);
382 385
383 return 0; 386 return 0;
384} 387}
@@ -392,7 +395,8 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev,
392 unsigned long flags; 395 unsigned long flags;
393 int err = -EINVAL; 396 int err = -EINVAL;
394 397
395 bcm43xx_lock_irqsafe(bcm, flags); 398 mutex_lock(&bcm->mutex);
399 spin_lock_irqsave(&bcm->irq_lock, flags);
396 if (data->frag.disabled) { 400 if (data->frag.disabled) {
397 bcm->ieee->fts = MAX_FRAG_THRESHOLD; 401 bcm->ieee->fts = MAX_FRAG_THRESHOLD;
398 err = 0; 402 err = 0;
@@ -403,7 +407,8 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev,
403 err = 0; 407 err = 0;
404 } 408 }
405 } 409 }
406 bcm43xx_unlock_irqsafe(bcm, flags); 410 spin_unlock_irqrestore(&bcm->irq_lock, flags);
411 mutex_unlock(&bcm->mutex);
407 412
408 return err; 413 return err;
409} 414}
@@ -414,13 +419,12 @@ static int bcm43xx_wx_get_frag(struct net_device *net_dev,
414 char *extra) 419 char *extra)
415{ 420{
416 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 421 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
417 unsigned long flags;
418 422
419 bcm43xx_lock_irqsafe(bcm, flags); 423 mutex_lock(&bcm->mutex);
420 data->frag.value = bcm->ieee->fts; 424 data->frag.value = bcm->ieee->fts;
421 data->frag.fixed = 0; 425 data->frag.fixed = 0;
422 data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); 426 data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
423 bcm43xx_unlock_irqsafe(bcm, flags); 427 mutex_unlock(&bcm->mutex);
424 428
425 return 0; 429 return 0;
426} 430}
@@ -442,7 +446,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
442 return -EOPNOTSUPP; 446 return -EOPNOTSUPP;
443 } 447 }
444 448
445 bcm43xx_lock_irqsafe(bcm, flags); 449 mutex_lock(&bcm->mutex);
450 spin_lock_irqsave(&bcm->irq_lock, flags);
446 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) 451 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
447 goto out_unlock; 452 goto out_unlock;
448 radio = bcm43xx_current_radio(bcm); 453 radio = bcm43xx_current_radio(bcm);
@@ -466,7 +471,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
466 err = 0; 471 err = 0;
467 472
468out_unlock: 473out_unlock:
469 bcm43xx_unlock_irqsafe(bcm, flags); 474 spin_unlock_irqrestore(&bcm->irq_lock, flags);
475 mutex_unlock(&bcm->mutex);
470 476
471 return err; 477 return err;
472} 478}
@@ -478,10 +484,9 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
478{ 484{
479 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 485 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
480 struct bcm43xx_radioinfo *radio; 486 struct bcm43xx_radioinfo *radio;
481 unsigned long flags;
482 int err = -ENODEV; 487 int err = -ENODEV;
483 488
484 bcm43xx_lock_irqsafe(bcm, flags); 489 mutex_lock(&bcm->mutex);
485 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) 490 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
486 goto out_unlock; 491 goto out_unlock;
487 radio = bcm43xx_current_radio(bcm); 492 radio = bcm43xx_current_radio(bcm);
@@ -493,7 +498,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
493 498
494 err = 0; 499 err = 0;
495out_unlock: 500out_unlock:
496 bcm43xx_unlock_irqsafe(bcm, flags); 501 mutex_unlock(&bcm->mutex);
497 502
498 return err; 503 return err;
499} 504}
@@ -580,7 +585,8 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
580 return -EINVAL; 585 return -EINVAL;
581 } 586 }
582 587
583 bcm43xx_lock_irqsafe(bcm, flags); 588 mutex_lock(&bcm->mutex);
589 spin_lock_irqsave(&bcm->irq_lock, flags);
584 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { 590 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
585 err = bcm43xx_radio_set_interference_mitigation(bcm, mode); 591 err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
586 if (err) { 592 if (err) {
@@ -595,7 +601,8 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
595 } else 601 } else
596 bcm43xx_current_radio(bcm)->interfmode = mode; 602 bcm43xx_current_radio(bcm)->interfmode = mode;
597 } 603 }
598 bcm43xx_unlock_irqsafe(bcm, flags); 604 spin_unlock_irqrestore(&bcm->irq_lock, flags);
605 mutex_unlock(&bcm->mutex);
599 606
600 return err; 607 return err;
601} 608}
@@ -606,12 +613,11 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
606 char *extra) 613 char *extra)
607{ 614{
608 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 615 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
609 unsigned long flags;
610 int mode; 616 int mode;
611 617
612 bcm43xx_lock_irqsafe(bcm, flags); 618 mutex_lock(&bcm->mutex);
613 mode = bcm43xx_current_radio(bcm)->interfmode; 619 mode = bcm43xx_current_radio(bcm)->interfmode;
614 bcm43xx_unlock_irqsafe(bcm, flags); 620 mutex_unlock(&bcm->mutex);
615 621
616 switch (mode) { 622 switch (mode) {
617 case BCM43xx_RADIO_INTERFMODE_NONE: 623 case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -641,9 +647,11 @@ static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
641 int on; 647 int on;
642 648
643 on = *((int *)extra); 649 on = *((int *)extra);
644 bcm43xx_lock_irqsafe(bcm, flags); 650 mutex_lock(&bcm->mutex);
651 spin_lock_irqsave(&bcm->irq_lock, flags);
645 bcm->short_preamble = !!on; 652 bcm->short_preamble = !!on;
646 bcm43xx_unlock_irqsafe(bcm, flags); 653 spin_unlock_irqrestore(&bcm->irq_lock, flags);
654 mutex_unlock(&bcm->mutex);
647 655
648 return 0; 656 return 0;
649} 657}
@@ -654,12 +662,11 @@ static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
654 char *extra) 662 char *extra)
655{ 663{
656 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 664 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
657 unsigned long flags;
658 int on; 665 int on;
659 666
660 bcm43xx_lock_irqsafe(bcm, flags); 667 mutex_lock(&bcm->mutex);
661 on = bcm->short_preamble; 668 on = bcm->short_preamble;
662 bcm43xx_unlock_irqsafe(bcm, flags); 669 mutex_unlock(&bcm->mutex);
663 670
664 if (on) 671 if (on)
665 strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); 672 strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
@@ -681,11 +688,13 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
681 688
682 on = *((int *)extra); 689 on = *((int *)extra);
683 690
684 bcm43xx_lock_irqsafe(bcm, flags); 691 mutex_lock(&bcm->mutex);
692 spin_lock_irqsave(&bcm->irq_lock, flags);
685 bcm->ieee->host_encrypt = !!on; 693 bcm->ieee->host_encrypt = !!on;
686 bcm->ieee->host_decrypt = !!on; 694 bcm->ieee->host_decrypt = !!on;
687 bcm->ieee->host_build_iv = !on; 695 bcm->ieee->host_build_iv = !on;
688 bcm43xx_unlock_irqsafe(bcm, flags); 696 spin_unlock_irqrestore(&bcm->irq_lock, flags);
697 mutex_unlock(&bcm->mutex);
689 698
690 return 0; 699 return 0;
691} 700}
@@ -696,12 +705,11 @@ static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
696 char *extra) 705 char *extra)
697{ 706{
698 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 707 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
699 unsigned long flags;
700 int on; 708 int on;
701 709
702 bcm43xx_lock_irqsafe(bcm, flags); 710 mutex_lock(&bcm->mutex);
703 on = bcm->ieee->host_encrypt; 711 on = bcm->ieee->host_encrypt;
704 bcm43xx_unlock_irqsafe(bcm, flags); 712 mutex_unlock(&bcm->mutex);
705 713
706 if (on) 714 if (on)
707 strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); 715 strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
@@ -764,11 +772,13 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
764 if (!sprom) 772 if (!sprom)
765 goto out; 773 goto out;
766 774
767 bcm43xx_lock_irqsafe(bcm, flags); 775 mutex_lock(&bcm->mutex);
776 spin_lock_irqsave(&bcm->irq_lock, flags);
768 err = -ENODEV; 777 err = -ENODEV;
769 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) 778 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
770 err = bcm43xx_sprom_read(bcm, sprom); 779 err = bcm43xx_sprom_read(bcm, sprom);
771 bcm43xx_unlock_irqsafe(bcm, flags); 780 spin_unlock_irqrestore(&bcm->irq_lock, flags);
781 mutex_unlock(&bcm->mutex);
772 if (!err) 782 if (!err)
773 data->data.length = sprom2hex(sprom, extra); 783 data->data.length = sprom2hex(sprom, extra);
774 kfree(sprom); 784 kfree(sprom);
@@ -809,11 +819,15 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
809 if (err) 819 if (err)
810 goto out_kfree; 820 goto out_kfree;
811 821
812 bcm43xx_lock_irqsafe(bcm, flags); 822 mutex_lock(&bcm->mutex);
823 spin_lock_irqsave(&bcm->irq_lock, flags);
824 spin_lock(&bcm->leds_lock);
813 err = -ENODEV; 825 err = -ENODEV;
814 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) 826 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
815 err = bcm43xx_sprom_write(bcm, sprom); 827 err = bcm43xx_sprom_write(bcm, sprom);
816 bcm43xx_unlock_irqsafe(bcm, flags); 828 spin_unlock(&bcm->leds_lock);
829 spin_unlock_irqrestore(&bcm->irq_lock, flags);
830 mutex_unlock(&bcm->mutex);
817out_kfree: 831out_kfree:
818 kfree(sprom); 832 kfree(sprom);
819out: 833out:
@@ -827,6 +841,10 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d
827 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 841 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
828 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); 842 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
829 struct iw_statistics *wstats; 843 struct iw_statistics *wstats;
844 struct ieee80211_network *network = NULL;
845 static int tmp_level = 0;
846 static int tmp_qual = 0;
847 unsigned long flags;
830 848
831 wstats = &bcm->stats.wstats; 849 wstats = &bcm->stats.wstats;
832 if (!mac->associated) { 850 if (!mac->associated) {
@@ -844,16 +862,28 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d
844 wstats->qual.level = 0; 862 wstats->qual.level = 0;
845 wstats->qual.noise = 0; 863 wstats->qual.noise = 0;
846 wstats->qual.updated = 7; 864 wstats->qual.updated = 7;
847 wstats->qual.updated |= IW_QUAL_NOISE_INVALID | 865 wstats->qual.updated |= IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
848 IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
849 return wstats; 866 return wstats;
850 } 867 }
851 /* fill in the real statistics when iface associated */ 868 /* fill in the real statistics when iface associated */
852 wstats->qual.qual = 100; // TODO: get the real signal quality 869 spin_lock_irqsave(&mac->ieee->lock, flags);
853 wstats->qual.level = 3 - bcm->stats.link_quality; 870 list_for_each_entry(network, &mac->ieee->network_list, list) {
871 if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) {
872 if (!tmp_level) { /* get initial values */
873 tmp_level = network->stats.signal;
874 tmp_qual = network->stats.rssi;
875 } else { /* smooth results */
876 tmp_level = (15 * tmp_level + network->stats.signal)/16;
877 tmp_qual = (15 * tmp_qual + network->stats.rssi)/16;
878 }
879 break;
880 }
881 }
882 spin_unlock_irqrestore(&mac->ieee->lock, flags);
883 wstats->qual.level = tmp_level;
884 wstats->qual.qual = 100 * tmp_qual / RX_RSSI_MAX;
854 wstats->qual.noise = bcm->stats.noise; 885 wstats->qual.noise = bcm->stats.noise;
855 wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | 886 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
856 IW_QUAL_NOISE_UPDATED;
857 wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable; 887 wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
858 wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded; 888 wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
859 wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa; 889 wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
index 6dbd855b3647..c0efbfe605a5 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -492,16 +492,15 @@ int bcm43xx_rx(struct bcm43xx_private *bcm,
492 492
493 memset(&stats, 0, sizeof(stats)); 493 memset(&stats, 0, sizeof(stats));
494 stats.mac_time = le16_to_cpu(rxhdr->mactime); 494 stats.mac_time = le16_to_cpu(rxhdr->mactime);
495 stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, 495 stats.rssi = rxhdr->rssi;
496 stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
496 !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), 497 !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
497 !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); 498 !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
498 stats.signal = rxhdr->signal_quality; //FIXME
499//TODO stats.noise = 499//TODO stats.noise =
500 if (is_ofdm) 500 if (is_ofdm)
501 stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp); 501 stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
502 else 502 else
503 stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp); 503 stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
504//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
505 stats.received_channel = radio->channel; 504 stats.received_channel = radio->channel;
506//TODO stats.control = 505//TODO stats.control =
507 stats.mask = IEEE80211_STATMASK_SIGNAL | 506 stats.mask = IEEE80211_STATMASK_SIGNAL |
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index b3300ffe4eec..758459e72f3d 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -2667,7 +2667,7 @@ static void ipw_fw_dma_abort(struct ipw_priv *priv)
2667 2667
2668 IPW_DEBUG_FW(">> :\n"); 2668 IPW_DEBUG_FW(">> :\n");
2669 2669
2670 //set the Stop and Abort bit 2670 /* set the Stop and Abort bit */
2671 control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT; 2671 control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT;
2672 ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); 2672 ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control);
2673 priv->sram_desc.last_cb_index = 0; 2673 priv->sram_desc.last_cb_index = 0;
@@ -3002,8 +3002,6 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
3002 if (rc < 0) 3002 if (rc < 0)
3003 return rc; 3003 return rc;
3004 3004
3005// spin_lock_irqsave(&priv->lock, flags);
3006
3007 for (addr = IPW_SHARED_LOWER_BOUND; 3005 for (addr = IPW_SHARED_LOWER_BOUND;
3008 addr < IPW_REGISTER_DOMAIN1_END; addr += 4) { 3006 addr < IPW_REGISTER_DOMAIN1_END; addr += 4) {
3009 ipw_write32(priv, addr, 0); 3007 ipw_write32(priv, addr, 0);
@@ -3097,8 +3095,6 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
3097 firmware have problem getting alive resp. */ 3095 firmware have problem getting alive resp. */
3098 ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0); 3096 ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0);
3099 3097
3100// spin_unlock_irqrestore(&priv->lock, flags);
3101
3102 return rc; 3098 return rc;
3103} 3099}
3104 3100
@@ -6387,13 +6383,6 @@ static int ipw_wx_set_genie(struct net_device *dev,
6387 (wrqu->data.length && extra == NULL)) 6383 (wrqu->data.length && extra == NULL))
6388 return -EINVAL; 6384 return -EINVAL;
6389 6385
6390 //mutex_lock(&priv->mutex);
6391
6392 //if (!ieee->wpa_enabled) {
6393 // err = -EOPNOTSUPP;
6394 // goto out;
6395 //}
6396
6397 if (wrqu->data.length) { 6386 if (wrqu->data.length) {
6398 buf = kmalloc(wrqu->data.length, GFP_KERNEL); 6387 buf = kmalloc(wrqu->data.length, GFP_KERNEL);
6399 if (buf == NULL) { 6388 if (buf == NULL) {
@@ -6413,7 +6402,6 @@ static int ipw_wx_set_genie(struct net_device *dev,
6413 6402
6414 ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); 6403 ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);
6415 out: 6404 out:
6416 //mutex_unlock(&priv->mutex);
6417 return err; 6405 return err;
6418} 6406}
6419 6407
@@ -6426,13 +6414,6 @@ static int ipw_wx_get_genie(struct net_device *dev,
6426 struct ieee80211_device *ieee = priv->ieee; 6414 struct ieee80211_device *ieee = priv->ieee;
6427 int err = 0; 6415 int err = 0;
6428 6416
6429 //mutex_lock(&priv->mutex);
6430
6431 //if (!ieee->wpa_enabled) {
6432 // err = -EOPNOTSUPP;
6433 // goto out;
6434 //}
6435
6436 if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) { 6417 if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) {
6437 wrqu->data.length = 0; 6418 wrqu->data.length = 0;
6438 goto out; 6419 goto out;
@@ -6447,7 +6428,6 @@ static int ipw_wx_get_genie(struct net_device *dev,
6447 memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); 6428 memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len);
6448 6429
6449 out: 6430 out:
6450 //mutex_unlock(&priv->mutex);
6451 return err; 6431 return err;
6452} 6432}
6453 6433
@@ -6558,7 +6538,6 @@ static int ipw_wx_set_auth(struct net_device *dev,
6558 ieee->ieee802_1x = param->value; 6538 ieee->ieee802_1x = param->value;
6559 break; 6539 break;
6560 6540
6561 //case IW_AUTH_ROAMING_CONTROL:
6562 case IW_AUTH_PRIVACY_INVOKED: 6541 case IW_AUTH_PRIVACY_INVOKED:
6563 ieee->privacy_invoked = param->value; 6542 ieee->privacy_invoked = param->value;
6564 break; 6543 break;
@@ -6680,7 +6659,7 @@ static int ipw_wx_set_mlme(struct net_device *dev,
6680 6659
6681 switch (mlme->cmd) { 6660 switch (mlme->cmd) {
6682 case IW_MLME_DEAUTH: 6661 case IW_MLME_DEAUTH:
6683 // silently ignore 6662 /* silently ignore */
6684 break; 6663 break;
6685 6664
6686 case IW_MLME_DISASSOC: 6665 case IW_MLME_DISASSOC:
@@ -9766,7 +9745,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
9766 return 0; 9745 return 0;
9767} 9746}
9768 9747
9769#endif // CONFIG_IPW2200_MONITOR 9748#endif /* CONFIG_IPW2200_MONITOR */
9770 9749
9771static int ipw_wx_reset(struct net_device *dev, 9750static int ipw_wx_reset(struct net_device *dev,
9772 struct iw_request_info *info, 9751 struct iw_request_info *info,
@@ -10009,7 +9988,7 @@ static void init_sys_config(struct ipw_sys_config *sys_config)
10009 sys_config->dot11g_auto_detection = 0; 9988 sys_config->dot11g_auto_detection = 0;
10010 sys_config->enable_cts_to_self = 0; 9989 sys_config->enable_cts_to_self = 0;
10011 sys_config->bt_coexist_collision_thr = 0; 9990 sys_config->bt_coexist_collision_thr = 0;
10012 sys_config->pass_noise_stats_to_host = 1; //1 -- fix for 256 9991 sys_config->pass_noise_stats_to_host = 1; /* 1 -- fix for 256 */
10013 sys_config->silence_threshold = 0x1e; 9992 sys_config->silence_threshold = 0x1e;
10014} 9993}
10015 9994
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 989599ad33ef..0c30fe7e8f7f 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -35,10 +35,14 @@
35 35
36#include <net/iw_handler.h> /* New driver API */ 36#include <net/iw_handler.h> /* New driver API */
37 37
38#define KEY_SIZE_WEP104 13 /* 104/128-bit WEP keys */
39#define KEY_SIZE_WEP40 5 /* 40/64-bit WEP keys */
40/* KEY_SIZE_TKIP should match isl_oid.h, struct obj_key.key[] size */
41#define KEY_SIZE_TKIP 32 /* TKIP keys */
38 42
39static void prism54_wpa_ie_add(islpci_private *priv, u8 *bssid, 43static void prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
40 u8 *wpa_ie, size_t wpa_ie_len); 44 u8 *wpa_ie, size_t wpa_ie_len);
41static size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie); 45static size_t prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie);
42static int prism54_set_wpa(struct net_device *, struct iw_request_info *, 46static int prism54_set_wpa(struct net_device *, struct iw_request_info *,
43 __u32 *, char *); 47 __u32 *, char *);
44 48
@@ -468,6 +472,9 @@ prism54_get_range(struct net_device *ndev, struct iw_request_info *info,
468 range->event_capa[1] = IW_EVENT_CAPA_K_1; 472 range->event_capa[1] = IW_EVENT_CAPA_K_1;
469 range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM); 473 range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM);
470 474
475 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
476 IW_ENC_CAPA_CIPHER_TKIP;
477
471 if (islpci_get_state(priv) < PRV_STATE_INIT) 478 if (islpci_get_state(priv) < PRV_STATE_INIT)
472 return 0; 479 return 0;
473 480
@@ -567,6 +574,8 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev,
567 struct iw_event iwe; /* Temporary buffer */ 574 struct iw_event iwe; /* Temporary buffer */
568 short cap; 575 short cap;
569 islpci_private *priv = netdev_priv(ndev); 576 islpci_private *priv = netdev_priv(ndev);
577 u8 wpa_ie[MAX_WPA_IE_LEN];
578 size_t wpa_ie_len;
570 579
571 /* The first entry must be the MAC address */ 580 /* The first entry must be the MAC address */
572 memcpy(iwe.u.ap_addr.sa_data, bss->address, 6); 581 memcpy(iwe.u.ap_addr.sa_data, bss->address, 6);
@@ -627,27 +636,13 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev,
627 current_ev = 636 current_ev =
628 iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); 637 iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
629 638
630 if (priv->wpa) { 639 /* Add WPA/RSN Information Element, if any */
631 u8 wpa_ie[MAX_WPA_IE_LEN]; 640 wpa_ie_len = prism54_wpa_bss_ie_get(priv, bss->address, wpa_ie);
632 char *buf, *p; 641 if (wpa_ie_len > 0) {
633 size_t wpa_ie_len; 642 iwe.cmd = IWEVGENIE;
634 int i; 643 iwe.u.data.length = min(wpa_ie_len, (size_t)MAX_WPA_IE_LEN);
635 644 current_ev = iwe_stream_add_point(current_ev, end_buf,
636 wpa_ie_len = prism54_wpa_ie_get(priv, bss->address, wpa_ie); 645 &iwe, wpa_ie);
637 if (wpa_ie_len > 0 &&
638 (buf = kmalloc(wpa_ie_len * 2 + 10, GFP_ATOMIC))) {
639 p = buf;
640 p += sprintf(p, "wpa_ie=");
641 for (i = 0; i < wpa_ie_len; i++) {
642 p += sprintf(p, "%02x", wpa_ie[i]);
643 }
644 memset(&iwe, 0, sizeof (iwe));
645 iwe.cmd = IWEVCUSTOM;
646 iwe.u.data.length = strlen(buf);
647 current_ev = iwe_stream_add_point(current_ev, end_buf,
648 &iwe, buf);
649 kfree(buf);
650 }
651 } 646 }
652 return current_ev; 647 return current_ev;
653} 648}
@@ -1051,12 +1046,24 @@ prism54_set_encode(struct net_device *ndev, struct iw_request_info *info,
1051 current_index = r.u; 1046 current_index = r.u;
1052 /* Verify that the key is not marked as invalid */ 1047 /* Verify that the key is not marked as invalid */
1053 if (!(dwrq->flags & IW_ENCODE_NOKEY)) { 1048 if (!(dwrq->flags & IW_ENCODE_NOKEY)) {
1054 key.length = dwrq->length > sizeof (key.key) ? 1049 if (dwrq->length > KEY_SIZE_TKIP) {
1055 sizeof (key.key) : dwrq->length; 1050 /* User-provided key data too big */
1056 memcpy(key.key, extra, key.length); 1051 return -EINVAL;
1057 if (key.length == 32) 1052 }
1058 /* we want WPA-PSK */ 1053 if (dwrq->length > KEY_SIZE_WEP104) {
1054 /* WPA-PSK TKIP */
1059 key.type = DOT11_PRIV_TKIP; 1055 key.type = DOT11_PRIV_TKIP;
1056 key.length = KEY_SIZE_TKIP;
1057 } else if (dwrq->length > KEY_SIZE_WEP40) {
1058 /* WEP 104/128 */
1059 key.length = KEY_SIZE_WEP104;
1060 } else {
1061 /* WEP 40/64 */
1062 key.length = KEY_SIZE_WEP40;
1063 }
1064 memset(key.key, 0, sizeof (key.key));
1065 memcpy(key.key, extra, dwrq->length);
1066
1060 if ((index < 0) || (index > 3)) 1067 if ((index < 0) || (index > 3))
1061 /* no index provided use the current one */ 1068 /* no index provided use the current one */
1062 index = current_index; 1069 index = current_index;
@@ -1210,6 +1217,489 @@ prism54_set_txpower(struct net_device *ndev, struct iw_request_info *info,
1210 } 1217 }
1211} 1218}
1212 1219
1220static int prism54_set_genie(struct net_device *ndev,
1221 struct iw_request_info *info,
1222 struct iw_point *data, char *extra)
1223{
1224 islpci_private *priv = netdev_priv(ndev);
1225 int alen, ret = 0;
1226 struct obj_attachment *attach;
1227
1228 if (data->length > MAX_WPA_IE_LEN ||
1229 (data->length && extra == NULL))
1230 return -EINVAL;
1231
1232 memcpy(priv->wpa_ie, extra, data->length);
1233 priv->wpa_ie_len = data->length;
1234
1235 alen = sizeof(*attach) + priv->wpa_ie_len;
1236 attach = kzalloc(alen, GFP_KERNEL);
1237 if (attach == NULL)
1238 return -ENOMEM;
1239
1240#define WLAN_FC_TYPE_MGMT 0
1241#define WLAN_FC_STYPE_ASSOC_REQ 0
1242#define WLAN_FC_STYPE_REASSOC_REQ 2
1243
1244 /* Note: endianness is covered by mgt_set_varlen */
1245 attach->type = (WLAN_FC_TYPE_MGMT << 2) |
1246 (WLAN_FC_STYPE_ASSOC_REQ << 4);
1247 attach->id = -1;
1248 attach->size = priv->wpa_ie_len;
1249 memcpy(attach->data, extra, priv->wpa_ie_len);
1250
1251 ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach,
1252 priv->wpa_ie_len);
1253 if (ret == 0) {
1254 attach->type = (WLAN_FC_TYPE_MGMT << 2) |
1255 (WLAN_FC_STYPE_REASSOC_REQ << 4);
1256
1257 ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach,
1258 priv->wpa_ie_len);
1259 if (ret == 0)
1260 printk(KERN_DEBUG "%s: WPA IE Attachment was set\n",
1261 ndev->name);
1262 }
1263
1264 kfree(attach);
1265 return ret;
1266}
1267
1268
1269static int prism54_get_genie(struct net_device *ndev,
1270 struct iw_request_info *info,
1271 struct iw_point *data, char *extra)
1272{
1273 islpci_private *priv = netdev_priv(ndev);
1274 int len = priv->wpa_ie_len;
1275
1276 if (len <= 0) {
1277 data->length = 0;
1278 return 0;
1279 }
1280
1281 if (data->length < len)
1282 return -E2BIG;
1283
1284 data->length = len;
1285 memcpy(extra, priv->wpa_ie, len);
1286
1287 return 0;
1288}
1289
1290static int prism54_set_auth(struct net_device *ndev,
1291 struct iw_request_info *info,
1292 union iwreq_data *wrqu, char *extra)
1293{
1294 islpci_private *priv = netdev_priv(ndev);
1295 struct iw_param *param = &wrqu->param;
1296 u32 mlmelevel = 0, authen = 0, dot1x = 0;
1297 u32 exunencrypt = 0, privinvoked = 0, wpa = 0;
1298 u32 old_wpa;
1299 int ret = 0;
1300 union oid_res_t r;
1301
1302 if (islpci_get_state(priv) < PRV_STATE_INIT)
1303 return 0;
1304
1305 /* first get the flags */
1306 down_write(&priv->mib_sem);
1307 wpa = old_wpa = priv->wpa;
1308 up_write(&priv->mib_sem);
1309 ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
1310 authen = r.u;
1311 ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
1312 privinvoked = r.u;
1313 ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
1314 exunencrypt = r.u;
1315 ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r);
1316 dot1x = r.u;
1317 ret = mgt_get_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, NULL, &r);
1318 mlmelevel = r.u;
1319
1320 if (ret < 0)
1321 goto out;
1322
1323 switch (param->flags & IW_AUTH_INDEX) {
1324 case IW_AUTH_CIPHER_PAIRWISE:
1325 case IW_AUTH_CIPHER_GROUP:
1326 case IW_AUTH_KEY_MGMT:
1327 break;
1328
1329 case IW_AUTH_WPA_ENABLED:
1330 /* Do the same thing as IW_AUTH_WPA_VERSION */
1331 if (param->value) {
1332 wpa = 1;
1333 privinvoked = 1; /* For privacy invoked */
1334 exunencrypt = 1; /* Filter out all unencrypted frames */
1335 dot1x = 0x01; /* To enable eap filter */
1336 mlmelevel = DOT11_MLME_EXTENDED;
1337 authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
1338 } else {
1339 wpa = 0;
1340 privinvoked = 0;
1341 exunencrypt = 0; /* Do not filter un-encrypted data */
1342 dot1x = 0;
1343 mlmelevel = DOT11_MLME_AUTO;
1344 }
1345 break;
1346
1347 case IW_AUTH_WPA_VERSION:
1348 if (param->value & IW_AUTH_WPA_VERSION_DISABLED) {
1349 wpa = 0;
1350 privinvoked = 0;
1351 exunencrypt = 0; /* Do not filter un-encrypted data */
1352 dot1x = 0;
1353 mlmelevel = DOT11_MLME_AUTO;
1354 } else {
1355 if (param->value & IW_AUTH_WPA_VERSION_WPA)
1356 wpa = 1;
1357 else if (param->value & IW_AUTH_WPA_VERSION_WPA2)
1358 wpa = 2;
1359 privinvoked = 1; /* For privacy invoked */
1360 exunencrypt = 1; /* Filter out all unencrypted frames */
1361 dot1x = 0x01; /* To enable eap filter */
1362 mlmelevel = DOT11_MLME_EXTENDED;
1363 authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
1364 }
1365 break;
1366
1367 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1368 dot1x = param->value ? 1 : 0;
1369 break;
1370
1371 case IW_AUTH_PRIVACY_INVOKED:
1372 privinvoked = param->value ? 1 : 0;
1373
1374 case IW_AUTH_DROP_UNENCRYPTED:
1375 exunencrypt = param->value ? 1 : 0;
1376 break;
1377
1378 case IW_AUTH_80211_AUTH_ALG:
1379 if (param->value & IW_AUTH_ALG_SHARED_KEY) {
1380 /* Only WEP uses _SK and _BOTH */
1381 if (wpa > 0) {
1382 ret = -EINVAL;
1383 goto out;
1384 }
1385 authen = DOT11_AUTH_SK;
1386 } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1387 authen = DOT11_AUTH_OS;
1388 } else {
1389 ret = -EINVAL;
1390 goto out;
1391 }
1392 break;
1393
1394 default:
1395 return -EOPNOTSUPP;
1396 }
1397
1398 /* Set all the values */
1399 down_write(&priv->mib_sem);
1400 priv->wpa = wpa;
1401 up_write(&priv->mib_sem);
1402 mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen);
1403 mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &privinvoked);
1404 mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &exunencrypt);
1405 mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x);
1406 mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlmelevel);
1407
1408out:
1409 return ret;
1410}
1411
1412static int prism54_get_auth(struct net_device *ndev,
1413 struct iw_request_info *info,
1414 union iwreq_data *wrqu, char *extra)
1415{
1416 islpci_private *priv = netdev_priv(ndev);
1417 struct iw_param *param = &wrqu->param;
1418 u32 wpa = 0;
1419 int ret = 0;
1420 union oid_res_t r;
1421
1422 if (islpci_get_state(priv) < PRV_STATE_INIT)
1423 return 0;
1424
1425 /* first get the flags */
1426 down_write(&priv->mib_sem);
1427 wpa = priv->wpa;
1428 up_write(&priv->mib_sem);
1429
1430 switch (param->flags & IW_AUTH_INDEX) {
1431 case IW_AUTH_CIPHER_PAIRWISE:
1432 case IW_AUTH_CIPHER_GROUP:
1433 case IW_AUTH_KEY_MGMT:
1434 /*
1435 * wpa_supplicant will control these internally
1436 */
1437 ret = -EOPNOTSUPP;
1438 break;
1439
1440 case IW_AUTH_WPA_VERSION:
1441 switch (wpa) {
1442 case 1:
1443 param->value = IW_AUTH_WPA_VERSION_WPA;
1444 break;
1445 case 2:
1446 param->value = IW_AUTH_WPA_VERSION_WPA2;
1447 break;
1448 case 0:
1449 default:
1450 param->value = IW_AUTH_WPA_VERSION_DISABLED;
1451 break;
1452 }
1453 break;
1454
1455 case IW_AUTH_DROP_UNENCRYPTED:
1456 ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
1457 if (ret >= 0)
1458 param->value = r.u > 0 ? 1 : 0;
1459 break;
1460
1461 case IW_AUTH_80211_AUTH_ALG:
1462 ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
1463 if (ret >= 0) {
1464 switch (r.u) {
1465 case DOT11_AUTH_OS:
1466 param->value = IW_AUTH_ALG_OPEN_SYSTEM;
1467 break;
1468 case DOT11_AUTH_BOTH:
1469 case DOT11_AUTH_SK:
1470 param->value = IW_AUTH_ALG_SHARED_KEY;
1471 case DOT11_AUTH_NONE:
1472 default:
1473 param->value = 0;
1474 break;
1475 }
1476 }
1477 break;
1478
1479 case IW_AUTH_WPA_ENABLED:
1480 param->value = wpa > 0 ? 1 : 0;
1481 break;
1482
1483 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1484 ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r);
1485 if (ret >= 0)
1486 param->value = r.u > 0 ? 1 : 0;
1487 break;
1488
1489 case IW_AUTH_PRIVACY_INVOKED:
1490 ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
1491 if (ret >= 0)
1492 param->value = r.u > 0 ? 1 : 0;
1493 break;
1494
1495 default:
1496 return -EOPNOTSUPP;
1497 }
1498 return ret;
1499}
1500
1501static int prism54_set_encodeext(struct net_device *ndev,
1502 struct iw_request_info *info,
1503 union iwreq_data *wrqu,
1504 char *extra)
1505{
1506 islpci_private *priv = netdev_priv(ndev);
1507 struct iw_point *encoding = &wrqu->encoding;
1508 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1509 int idx, alg = ext->alg, set_key = 1;
1510 union oid_res_t r;
1511 int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0;
1512 int ret = 0;
1513
1514 if (islpci_get_state(priv) < PRV_STATE_INIT)
1515 return 0;
1516
1517 /* Determine and validate the key index */
1518 idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
1519 if (idx) {
1520 if (idx < 0 || idx > 3)
1521 return -EINVAL;
1522 } else {
1523 ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
1524 if (ret < 0)
1525 goto out;
1526 idx = r.u;
1527 }
1528
1529 if (encoding->flags & IW_ENCODE_DISABLED)
1530 alg = IW_ENCODE_ALG_NONE;
1531
1532 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1533 /* Only set transmit key index here, actual
1534 * key is set below if needed.
1535 */
1536 ret = mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, &idx);
1537 set_key = ext->key_len > 0 ? 1 : 0;
1538 }
1539
1540 if (set_key) {
1541 struct obj_key key = { DOT11_PRIV_WEP, 0, "" };
1542 switch (alg) {
1543 case IW_ENCODE_ALG_NONE:
1544 break;
1545 case IW_ENCODE_ALG_WEP:
1546 if (ext->key_len > KEY_SIZE_WEP104) {
1547 ret = -EINVAL;
1548 goto out;
1549 }
1550 if (ext->key_len > KEY_SIZE_WEP40)
1551 key.length = KEY_SIZE_WEP104;
1552 else
1553 key.length = KEY_SIZE_WEP40;
1554 break;
1555 case IW_ENCODE_ALG_TKIP:
1556 if (ext->key_len > KEY_SIZE_TKIP) {
1557 ret = -EINVAL;
1558 goto out;
1559 }
1560 key.type = DOT11_PRIV_TKIP;
1561 key.length = KEY_SIZE_TKIP;
1562 default:
1563 return -EINVAL;
1564 }
1565
1566 if (key.length) {
1567 memset(key.key, 0, sizeof(key.key));
1568 memcpy(key.key, ext->key, ext->key_len);
1569 ret = mgt_set_request(priv, DOT11_OID_DEFKEYX, idx,
1570 &key);
1571 if (ret < 0)
1572 goto out;
1573 }
1574 }
1575
1576 /* Read the flags */
1577 if (encoding->flags & IW_ENCODE_DISABLED) {
1578 /* Encoding disabled,
1579 * authen = DOT11_AUTH_OS;
1580 * invoke = 0;
1581 * exunencrypt = 0; */
1582 }
1583 if (encoding->flags & IW_ENCODE_OPEN) {
1584 /* Encode but accept non-encoded packets. No auth */
1585 invoke = 1;
1586 }
1587 if (encoding->flags & IW_ENCODE_RESTRICTED) {
1588 /* Refuse non-encoded packets. Auth */
1589 authen = DOT11_AUTH_BOTH;
1590 invoke = 1;
1591 exunencrypt = 1;
1592 }
1593
1594 /* do the change if requested */
1595 if (encoding->flags & IW_ENCODE_MODE) {
1596 ret = mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0,
1597 &authen);
1598 ret = mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0,
1599 &invoke);
1600 ret = mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0,
1601 &exunencrypt);
1602 }
1603
1604out:
1605 return ret;
1606}
1607
1608
1609static int prism54_get_encodeext(struct net_device *ndev,
1610 struct iw_request_info *info,
1611 union iwreq_data *wrqu,
1612 char *extra)
1613{
1614 islpci_private *priv = netdev_priv(ndev);
1615 struct iw_point *encoding = &wrqu->encoding;
1616 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1617 int idx, max_key_len;
1618 union oid_res_t r;
1619 int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0, wpa = 0;
1620 int ret = 0;
1621
1622 if (islpci_get_state(priv) < PRV_STATE_INIT)
1623 return 0;
1624
1625 /* first get the flags */
1626 ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
1627 authen = r.u;
1628 ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
1629 invoke = r.u;
1630 ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
1631 exunencrypt = r.u;
1632 if (ret < 0)
1633 goto out;
1634
1635 max_key_len = encoding->length - sizeof(*ext);
1636 if (max_key_len < 0)
1637 return -EINVAL;
1638
1639 idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
1640 if (idx) {
1641 if (idx < 0 || idx > 3)
1642 return -EINVAL;
1643 } else {
1644 ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
1645 if (ret < 0)
1646 goto out;
1647 idx = r.u;
1648 }
1649
1650 encoding->flags = idx + 1;
1651 memset(ext, 0, sizeof(*ext));
1652
1653 switch (authen) {
1654 case DOT11_AUTH_BOTH:
1655 case DOT11_AUTH_SK:
1656 wrqu->encoding.flags |= IW_ENCODE_RESTRICTED;
1657 case DOT11_AUTH_OS:
1658 default:
1659 wrqu->encoding.flags |= IW_ENCODE_OPEN;
1660 break;
1661 }
1662
1663 down_write(&priv->mib_sem);
1664 wpa = priv->wpa;
1665 up_write(&priv->mib_sem);
1666
1667 if (authen == DOT11_AUTH_OS && !exunencrypt && !invoke && !wpa) {
1668 /* No encryption */
1669 ext->alg = IW_ENCODE_ALG_NONE;
1670 ext->key_len = 0;
1671 wrqu->encoding.flags |= IW_ENCODE_DISABLED;
1672 } else {
1673 struct obj_key *key;
1674
1675 ret = mgt_get_request(priv, DOT11_OID_DEFKEYX, idx, NULL, &r);
1676 if (ret < 0)
1677 goto out;
1678 key = r.ptr;
1679 if (max_key_len < key->length) {
1680 ret = -E2BIG;
1681 goto out;
1682 }
1683 memcpy(ext->key, key->key, key->length);
1684 ext->key_len = key->length;
1685
1686 switch (key->type) {
1687 case DOT11_PRIV_TKIP:
1688 ext->alg = IW_ENCODE_ALG_TKIP;
1689 break;
1690 default:
1691 case DOT11_PRIV_WEP:
1692 ext->alg = IW_ENCODE_ALG_WEP;
1693 break;
1694 }
1695 wrqu->encoding.flags |= IW_ENCODE_ENABLED;
1696 }
1697
1698out:
1699 return ret;
1700}
1701
1702
1213static int 1703static int
1214prism54_reset(struct net_device *ndev, struct iw_request_info *info, 1704prism54_reset(struct net_device *ndev, struct iw_request_info *info,
1215 __u32 * uwrq, char *extra) 1705 __u32 * uwrq, char *extra)
@@ -1591,8 +2081,8 @@ static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 };
1591#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" 2081#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
1592 2082
1593static void 2083static void
1594prism54_wpa_ie_add(islpci_private *priv, u8 *bssid, 2084prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
1595 u8 *wpa_ie, size_t wpa_ie_len) 2085 u8 *wpa_ie, size_t wpa_ie_len)
1596{ 2086{
1597 struct list_head *ptr; 2087 struct list_head *ptr;
1598 struct islpci_bss_wpa_ie *bss = NULL; 2088 struct islpci_bss_wpa_ie *bss = NULL;
@@ -1658,7 +2148,7 @@ prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
1658} 2148}
1659 2149
1660static size_t 2150static size_t
1661prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie) 2151prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
1662{ 2152{
1663 struct list_head *ptr; 2153 struct list_head *ptr;
1664 struct islpci_bss_wpa_ie *bss = NULL; 2154 struct islpci_bss_wpa_ie *bss = NULL;
@@ -1683,14 +2173,14 @@ prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
1683} 2173}
1684 2174
1685void 2175void
1686prism54_wpa_ie_init(islpci_private *priv) 2176prism54_wpa_bss_ie_init(islpci_private *priv)
1687{ 2177{
1688 INIT_LIST_HEAD(&priv->bss_wpa_list); 2178 INIT_LIST_HEAD(&priv->bss_wpa_list);
1689 sema_init(&priv->wpa_sem, 1); 2179 sema_init(&priv->wpa_sem, 1);
1690} 2180}
1691 2181
1692void 2182void
1693prism54_wpa_ie_clean(islpci_private *priv) 2183prism54_wpa_bss_ie_clean(islpci_private *priv)
1694{ 2184{
1695 struct list_head *ptr, *n; 2185 struct list_head *ptr, *n;
1696 2186
@@ -1722,7 +2212,7 @@ prism54_process_bss_data(islpci_private *priv, u32 oid, u8 *addr,
1722 } 2212 }
1723 if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 && 2213 if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 &&
1724 memcmp(pos + 2, wpa_oid, 4) == 0) { 2214 memcmp(pos + 2, wpa_oid, 4) == 0) {
1725 prism54_wpa_ie_add(priv, addr, pos, pos[1] + 2); 2215 prism54_wpa_bss_ie_add(priv, addr, pos, pos[1] + 2);
1726 return; 2216 return;
1727 } 2217 }
1728 pos += 2 + pos[1]; 2218 pos += 2 + pos[1];
@@ -1879,7 +2369,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
1879 send_formatted_event(priv, "Associate request (ex)", mlme, 1); 2369 send_formatted_event(priv, "Associate request (ex)", mlme, 1);
1880 2370
1881 if (priv->iw_mode != IW_MODE_MASTER 2371 if (priv->iw_mode != IW_MODE_MASTER
1882 && mlmeex->state != DOT11_STATE_AUTHING) 2372 && mlmeex->state != DOT11_STATE_ASSOCING)
1883 break; 2373 break;
1884 2374
1885 confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); 2375 confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC);
@@ -1893,7 +2383,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
1893 confirm->state = 0; /* not used */ 2383 confirm->state = 0; /* not used */
1894 confirm->code = 0; 2384 confirm->code = 0;
1895 2385
1896 wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie); 2386 wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
1897 2387
1898 if (!wpa_ie_len) { 2388 if (!wpa_ie_len) {
1899 printk(KERN_DEBUG "No WPA IE found from " 2389 printk(KERN_DEBUG "No WPA IE found from "
@@ -1937,7 +2427,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
1937 confirm->state = 0; /* not used */ 2427 confirm->state = 0; /* not used */
1938 confirm->code = 0; 2428 confirm->code = 0;
1939 2429
1940 wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie); 2430 wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
1941 2431
1942 if (!wpa_ie_len) { 2432 if (!wpa_ie_len) {
1943 printk(KERN_DEBUG "No WPA IE found from " 2433 printk(KERN_DEBUG "No WPA IE found from "
@@ -2553,6 +3043,15 @@ static const iw_handler prism54_handler[] = {
2553 (iw_handler) prism54_get_encode, /* SIOCGIWENCODE */ 3043 (iw_handler) prism54_get_encode, /* SIOCGIWENCODE */
2554 (iw_handler) NULL, /* SIOCSIWPOWER */ 3044 (iw_handler) NULL, /* SIOCSIWPOWER */
2555 (iw_handler) NULL, /* SIOCGIWPOWER */ 3045 (iw_handler) NULL, /* SIOCGIWPOWER */
3046 NULL, /* -- hole -- */
3047 NULL, /* -- hole -- */
3048 (iw_handler) prism54_set_genie, /* SIOCSIWGENIE */
3049 (iw_handler) prism54_get_genie, /* SIOCGIWGENIE */
3050 (iw_handler) prism54_set_auth, /* SIOCSIWAUTH */
3051 (iw_handler) prism54_get_auth, /* SIOCGIWAUTH */
3052 (iw_handler) prism54_set_encodeext, /* SIOCSIWENCODEEXT */
3053 (iw_handler) prism54_get_encodeext, /* SIOCGIWENCODEEXT */
3054 NULL, /* SIOCSIWPMKSA */
2556}; 3055};
2557 3056
2558/* The low order bit identify a SET (0) or a GET (1) ioctl. */ 3057/* The low order bit identify a SET (0) or a GET (1) ioctl. */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h
index 46d5cde80c85..65f33acd0a42 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.h
+++ b/drivers/net/wireless/prism54/isl_ioctl.h
@@ -27,7 +27,7 @@
27 27
28#include <net/iw_handler.h> /* New driver API */ 28#include <net/iw_handler.h> /* New driver API */
29 29
30#define SUPPORTED_WIRELESS_EXT 16 30#define SUPPORTED_WIRELESS_EXT 19
31 31
32void prism54_mib_init(islpci_private *); 32void prism54_mib_init(islpci_private *);
33 33
@@ -39,8 +39,8 @@ void prism54_acl_clean(struct islpci_acl *);
39 39
40void prism54_process_trap(void *); 40void prism54_process_trap(void *);
41 41
42void prism54_wpa_ie_init(islpci_private *priv); 42void prism54_wpa_bss_ie_init(islpci_private *priv);
43void prism54_wpa_ie_clean(islpci_private *priv); 43void prism54_wpa_bss_ie_clean(islpci_private *priv);
44 44
45int prism54_set_mac_address(struct net_device *, void *); 45int prism54_set_mac_address(struct net_device *, void *);
46 46
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index 5ddf29599032..ab3c5a27efd9 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -715,7 +715,7 @@ islpci_alloc_memory(islpci_private *priv)
715 } 715 }
716 716
717 prism54_acl_init(&priv->acl); 717 prism54_acl_init(&priv->acl);
718 prism54_wpa_ie_init(priv); 718 prism54_wpa_bss_ie_init(priv);
719 if (mgt_init(priv)) 719 if (mgt_init(priv))
720 goto out_free; 720 goto out_free;
721 721
@@ -774,7 +774,7 @@ islpci_free_memory(islpci_private *priv)
774 774
775 /* Free the acces control list and the WPA list */ 775 /* Free the acces control list and the WPA list */
776 prism54_acl_clean(&priv->acl); 776 prism54_acl_clean(&priv->acl);
777 prism54_wpa_ie_clean(priv); 777 prism54_wpa_bss_ie_clean(priv);
778 mgt_clean(priv); 778 mgt_clean(priv);
779 779
780 return 0; 780 return 0;
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index 07053165e4c5..5049f37455b1 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -179,6 +179,8 @@ typedef struct {
179 struct list_head bss_wpa_list; 179 struct list_head bss_wpa_list;
180 int num_bss_wpa; 180 int num_bss_wpa;
181 struct semaphore wpa_sem; 181 struct semaphore wpa_sem;
182 u8 wpa_ie[MAX_WPA_IE_LEN];
183 size_t wpa_ie_len;
182 184
183 struct work_struct reset_task; 185 struct work_struct reset_task;
184 int reset_task_pending; 186 int reset_task_pending;
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c
index 9df232c2c863..440ef24b5fd1 100644
--- a/drivers/net/wireless/zd1211rw/zd_netdev.c
+++ b/drivers/net/wireless/zd1211rw/zd_netdev.c
@@ -72,10 +72,18 @@ static int iw_get_name(struct net_device *netdev,
72 struct iw_request_info *info, 72 struct iw_request_info *info,
73 union iwreq_data *req, char *extra) 73 union iwreq_data *req, char *extra)
74{ 74{
75 /* FIXME: check whether 802.11a will also supported, add also 75 /* FIXME: check whether 802.11a will also supported */
76 * zd1211B, if we support it. 76 strlcpy(req->name, "IEEE 802.11b/g", IFNAMSIZ);
77 */ 77 return 0;
78 strlcpy(req->name, "802.11g zd1211", IFNAMSIZ); 78}
79
80static int iw_get_nick(struct net_device *netdev,
81 struct iw_request_info *info,
82 union iwreq_data *req, char *extra)
83{
84 strcpy(extra, "zd1211");
85 req->data.length = strlen(extra) + 1;
86 req->data.flags = 1;
79 return 0; 87 return 0;
80} 88}
81 89
@@ -181,6 +189,7 @@ static int iw_get_encodeext(struct net_device *netdev,
181 189
182static const iw_handler zd_standard_iw_handlers[] = { 190static const iw_handler zd_standard_iw_handlers[] = {
183 WX(SIOCGIWNAME) = iw_get_name, 191 WX(SIOCGIWNAME) = iw_get_name,
192 WX(SIOCGIWNICKN) = iw_get_nick,
184 WX(SIOCSIWFREQ) = iw_set_freq, 193 WX(SIOCSIWFREQ) = iw_set_freq,
185 WX(SIOCGIWFREQ) = iw_get_freq, 194 WX(SIOCGIWFREQ) = iw_get_freq,
186 WX(SIOCSIWMODE) = iw_set_mode, 195 WX(SIOCSIWMODE) = iw_set_mode,
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 6320984126c7..96551da769fc 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -39,9 +39,11 @@ static struct usb_device_id usb_ids[] = {
39 { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, 39 { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
40 { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, 40 { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
41 { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, 41 { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
42 { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 },
42 /* ZD1211B */ 43 /* ZD1211B */
43 { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, 44 { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
44 { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, 45 { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
46 { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
45 {} 47 {}
46}; 48};
47 49