Re: [PATCH] b43: Use input-polldev for the rfkill switch

2007-10-10 Thread Michael Buesch
On Wednesday 10 October 2007 16:51:38 Dmitry Torokhov wrote:
   I don't think that broadcom driver should depend on RFKILL_INPUT...
   RFKILL_INPUT is a default link between input and rfkill layers but it
   is by no means a mandatory component.
  
   I think proper dependency should be:
  
   depends on B43  RFKILL  INPUT
   select INPUT_POLLDEV
  
 
  b43 rfkill support is useless without also having RFKILL_INPUT, as
  the button reporting is done though it.
  b43 does _not_ depend on RFKILL_INPUT, but b43-rfkill support is disabled,
  if there's no RFKILL_INPUT compiled.
 
 
 No, it is not. One can have a userspace daemon claiming the rfkill
 switch...

No, that's impossible with b43.

 We normally specify dependencies that are needed to build the code,
 not necessarily to use it. It's like various joystick drivers do not
 depend on joydev or evdev modules although most people would need
 these modules as well to use their joysticks. Or SCSI drivers don't
 depend on sd or sr being selected, etc, etc.

Yeah, well. As I said. This is not a dependency. It's an auto-select
option, which automatically selects the code.

-- 
Greetings Michael.
___
Bcm43xx-dev mailing list
Bcm43xx-dev@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev


4311: trouble with Fedora 8 Test 3

2007-10-10 Thread sean darcy
Compaq Presario C714NR, Intel GM965

uname -r
2.6.23-0.224.rc9.git6.fc8

lspci
01:00.0 Network controller: Broadcom Corporation BCM94311MCG wlan
mini-PCI (rev 02)

Installed b43-fwcutter and followed the instructions at
http://linuxwireless.org/en/users/Drivers/b43#devicefirmware

Got http://downloads.openwrt.org/sources/broadcom-wl-4.80.53.0.tar.bz2

untarred that file and ran
b43-fwcutter -w /lib/firmare broadcom-wl-4.80.53.0/kmod/wl_apsta.o

that seemed to work, and populated /lib/firmware/b43/ with a bunch of
*.fw files.

Then rmmod b43; modprobe -vv b43. No errors. Nothing in syslog.

modprobe also loaded cfg80211 and mac80211.

Shouldn't I have seen the firmware being loaded in dmesg, or syslog?

Nothing at all about the 4311 card in dmesg.

Made sure NetworkManager was working. Restarted it. I can see the icon.
No connection. If I connect the wire it starts up the wired connection.

dmesg does show this error:

ssb: rev 6000
WARNING: at drivers/ssb/main.c:889 ssb_tmslow_reject_bitmask() (Not tainted)

Call Trace:
 [88118878] :ssb:ssb_tmslow_reject_bitmask+0x76/0x7f
 [88119062] :ssb:ssb_device_is_enabled+0xf/0x39
 [8811b232] :ssb:ssb_pcicore_init+0x19/0x4a
 [881185e2] :ssb:ssb_attach_queued_buses+0x83/0x25e
 [88119ce8] :ssb:ssb_pci_get_invariants+0x0/0x2ba
 [88118be8] :ssb:ssb_bus_register+0x144/0x196
 [88118cea] :ssb:ssb_bus_pcibus_register+0x2a/0x4b
 [8811a5a9] :ssb:ssb_pcihost_probe+0x6f/0x9e
 [81137d8d] pci_device_probe+0xd0/0x137
 [811a1033] driver_probe_device+0xff/0x17c
 [811a11f8] __driver_attach+0x90/0xcc
 [811a1168] __driver_attach+0x0/0xcc
 [811a1168] __driver_attach+0x0/0xcc
 [811a03ca] bus_for_each_dev+0x43/0x6e
 [811a0742] bus_add_driver+0x7b/0x19d
 [81137f6f] __pci_register_driver+0x68/0x9a
 [880e9045] :ssb:ssb_modinit+0x45/0x5d
 [8105d8b3] sys_init_module+0x15d5/0x173a
 [8100bbfe] system_call+0x7e/0x83

ssb: Sonics Silicon Backplane found on PCI device :01:00.0

I also rmmod b43, and modprobe'd b43legacy. No help.

Any help appreciated.

sean
___
Bcm43xx-dev mailing list
Bcm43xx-dev@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev


Re: 4311: trouble with Fedora 8 Test 3

2007-10-10 Thread John W. Linville
On Wed, Oct 10, 2007 at 12:08:08PM -0400, sean darcy wrote:

 Nothing at all about the 4311 card in dmesg.
 
 Made sure NetworkManager was working. Restarted it. I can see the icon.
 No connection. If I connect the wire it starts up the wired connection.

Please post the output of this command:

cat /sys/bus/ssb/devices/ssb0\:0/uevent

I suspect that your device's core is too new to be supported.

 dmesg does show this error:
 
 ssb: rev 6000
 WARNING: at drivers/ssb/main.c:889 ssb_tmslow_reject_bitmask() (Not tainted)

Technically a warning, not an error. :-)

John
-- 
John W. Linville
[EMAIL PROTECTED]
___
Bcm43xx-dev mailing list
Bcm43xx-dev@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev


Re: 4311: trouble with Fedora 8 Test 3

2007-10-10 Thread Larry Finger
sean darcy wrote:
 Compaq Presario C714NR, Intel GM965
 
 uname -r
 2.6.23-0.224.rc9.git6.fc8
 
 lspci
 01:00.0 Network controller: Broadcom Corporation BCM94311MCG wlan
 mini-PCI (rev 02)

As John Linville suggested, rev 02 of the 4311's are not supported. At the 
moment, the reverse
engineers need to take apart the latest Broadcom driver and write the 
specifications for this
device. Until they find the time, this device will not work with either b43 or 
bcm43xx.

Sorry,

Larry

___
Bcm43xx-dev mailing list
Bcm43xx-dev@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev


[PATCH] b43legacy: LED triggers support

2007-10-10 Thread Larry Finger
Drive the LEDs through the generic LED triggers.

The patch to b43 by Michael Buesch [EMAIL PROTECTED] has been ported to 
b43legacy.

Signed-off-by: Larry Finger [EMAIL PROTECTED]
---

John,

This patch is to be applied to the 'everything' branch of wireless-2.6.

Larry
---

 drivers/net/wireless/b43legacy/Kconfig |6
 drivers/net/wireless/b43legacy/Makefile|   27 +
 drivers/net/wireless/b43legacy/b43legacy.h |6
 drivers/net/wireless/b43legacy/leds.c  |  411 -
 drivers/net/wireless/b43legacy/leds.h  |   61 ++--
 drivers/net/wireless/b43legacy/main.c  |   40 --
 drivers/net/wireless/b43legacy/radio.c |2
 7 files changed, 242 insertions(+), 311 deletions(-)

Index: wireless-2.6/drivers/net/wireless/b43legacy/Kconfig
===
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/Kconfig
+++ wireless-2.6/drivers/net/wireless/b43legacy/Kconfig
@@ -34,6 +34,12 @@ config B43LEGACY_PCICORE_AUTOSELECT
select SSB_DRIVER_PCICORE
default y
 
+# LED support
+config B43LEGACY_LEDS
+   bool
+   depends on MAC80211_LEDS
+   default y
+
 config B43LEGACY_DEBUG
bool Broadcom 43xx-legacy debugging
depends on B43LEGACY
Index: wireless-2.6/drivers/net/wireless/b43legacy/b43legacy.h
===
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/b43legacy.h
+++ wireless-2.6/drivers/net/wireless/b43legacy/b43legacy.h
@@ -663,8 +663,10 @@ struct b43legacy_wldev {
/* Various statistics about the physical device. */
struct b43legacy_stats stats;
 
-#define B43legacy_NR_LEDS  4
-   struct b43legacy_led leds[B43legacy_NR_LEDS];
+   /* The device LEDs. */
+   struct b43legacy_led led_tx;
+   struct b43legacy_led led_rx;
+   struct b43legacy_led led_assoc;
 
/* Reason code of the last interrupt. */
u32 irq_reason;
Index: wireless-2.6/drivers/net/wireless/b43legacy/leds.c
===
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/leds.c
+++ wireless-2.6/drivers/net/wireless/b43legacy/leds.c
@@ -1,13 +1,13 @@
 /*
 
-  Broadcom B43legacy wireless driver
+  Broadcom B43 wireless driver
+  LED control
 
   Copyright (c) 2005 Martin Langer [EMAIL PROTECTED],
-Stefano Brivio [EMAIL PROTECTED]
-Michael Buesch [EMAIL PROTECTED]
-Danny van Dyk [EMAIL PROTECTED]
-Andreas Jaggi [EMAIL PROTECTED]
-  Copyright (c) 2007 Larry Finger [EMAIL PROTECTED]
+  Copyright (c) 2005 Stefano Brivio [EMAIL PROTECTED]
+  Copyright (c) 2005-2007 Michael Buesch [EMAIL PROTECTED]
+  Copyright (c) 2005 Danny van Dyk [EMAIL PROTECTED]
+  Copyright (c) 2005 Andreas Jaggi [EMAIL PROTECTED]
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -26,273 +26,208 @@
 
 */
 
-#include leds.h
 #include b43legacy.h
-#include main.h
-
-static void b43legacy_led_changestate(struct b43legacy_led *led)
-{
-   struct b43legacy_wldev *dev = led-dev;
-   const int index = led-index;
-   u16 ledctl;
+#include leds.h
 
-   B43legacy_WARN_ON(!(index = 0  index  B43legacy_NR_LEDS));
-   B43legacy_WARN_ON(!led-blink_interval);
-   ledctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
-   ledctl ^= (1  index);
-   b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ledctl);
-}
 
-static void b43legacy_led_blink(unsigned long d)
+static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
+   bool activelow)
 {
-   struct b43legacy_led *led = (struct b43legacy_led *)d;
-   struct b43legacy_wldev *dev = led-dev;
+   struct b43legacy_wl *wl = dev-wl;
unsigned long flags;
+   u16 ctl;
 
-   spin_lock_irqsave(dev-wl-leds_lock, flags);
-   if (led-blink_interval) {
-   b43legacy_led_changestate(led);
-   mod_timer(led-blink_timer, jiffies + led-blink_interval);
-   }
-   spin_unlock_irqrestore(dev-wl-leds_lock, flags);
+   spin_lock_irqsave(wl-leds_lock, flags);
+   ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
+   if (activelow)
+   ctl = ~(1  led_index);
+   else
+   ctl |= (1  led_index);
+   b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
+   spin_unlock_irqrestore(wl-leds_lock, flags);
 }
 
-static void b43legacy_led_blink_start(struct b43legacy_led *led,
- unsigned long interval)
+static void b43legacy_led_turn_off(struct b43legacy_wldev *dev, u8 led_index,
+bool activelow)
 {
-   if (led-blink_interval)
-   return;
-   led-blink_interval = interval;
-   

[PATCH] b43legacy: RF-kill support

2007-10-10 Thread Larry Finger
This adds full support for the RFKILL button and the RFKILL LED trigger.

This is a port to b43legacy of a patch by Michael Buesch [EMAIL PROTECTED]
for b43.

Signed-off-by: Larry Finger[EMAIL PROTECTED]
---

John,

This patch is also to be applied to the everything branch of wireless-2.6.

Larry
---

 drivers/net/wireless/b43legacy/Kconfig |8 +
 drivers/net/wireless/b43legacy/Makefile|2
 drivers/net/wireless/b43legacy/b43legacy.h |5
 drivers/net/wireless/b43legacy/leds.c  |8 +
 drivers/net/wireless/b43legacy/main.c  |   18 ++-
 drivers/net/wireless/b43legacy/radio.c |   13 +-
 drivers/net/wireless/b43legacy/radio.h |2
 drivers/net/wireless/b43legacy/rfkill.c|  158 +
 drivers/net/wireless/b43legacy/rfkill.h|   51 +
 9 files changed, 250 insertions(+), 15 deletions(-)

Index: wireless-2.6/drivers/net/wireless/b43legacy/Kconfig
===
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/Kconfig
+++ wireless-2.6/drivers/net/wireless/b43legacy/Kconfig
@@ -37,7 +37,13 @@ config B43LEGACY_PCICORE_AUTOSELECT
 # LED support
 config B43LEGACY_LEDS
bool
-   depends on MAC80211_LEDS
+   depends on B43LEGACY  MAC80211_LEDS
+   default y
+
+# RFKILL support
+config B43LEGACY_RFKILL
+   bool
+   depends on B43LEGACY  RFKILL
default y
 
 config B43LEGACY_DEBUG
Index: wireless-2.6/drivers/net/wireless/b43legacy/Makefile
===
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/Makefile
+++ wireless-2.6/drivers/net/wireless/b43legacy/Makefile
@@ -5,6 +5,8 @@ b43legacy-y += phy.o
 b43legacy-y+= radio.o
 b43legacy-y+= sysfs.o
 b43legacy-y+= xmit.o
+# b43 RFKILL button support
+b43legacy-$(CONFIG_B43LEGACY_RFKILL)   += rfkill.o
 # b43legacy LED support
 b43legacy-$(CONFIG_B43LEGACY_LEDS) += leds.o
 # b43legacy debugging
Index: wireless-2.6/drivers/net/wireless/b43legacy/b43legacy.h
===
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/b43legacy.h
+++ wireless-2.6/drivers/net/wireless/b43legacy/b43legacy.h
@@ -19,6 +19,7 @@
 
 #include debugfs.h
 #include leds.h
+#include rfkill.h
 #include phy.h
 
 
@@ -592,6 +593,9 @@ struct b43legacy_wl {
u8 rng_initialized;
char rng_name[30 + 1];
 
+   /* The RF-kill button */
+   struct b43legacy_rfkill rfkill;
+
/* List of all wireless devices on this chip */
struct list_head devlist;
u8 nr_devs;
@@ -667,6 +671,7 @@ struct b43legacy_wldev {
struct b43legacy_led led_tx;
struct b43legacy_led led_rx;
struct b43legacy_led led_assoc;
+   struct b43legacy_led led_radio;
 
/* Reason code of the last interrupt. */
u32 irq_reason;
Index: wireless-2.6/drivers/net/wireless/b43legacy/main.c
===
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/main.c
+++ wireless-2.6/drivers/net/wireless/b43legacy/main.c
@@ -1993,7 +1993,7 @@ static bool b43legacy_is_hw_radio_enable
 /* This is the opposite of b43legacy_chip_init() */
 static void b43legacy_chip_exit(struct b43legacy_wldev *dev)
 {
-   b43legacy_radio_turn_off(dev);
+   b43legacy_radio_turn_off(dev, 1);
b43legacy_leds_exit(dev);
b43legacy_gpio_cleanup(dev);
/* firmware is released later */
@@ -2106,7 +2106,7 @@ out:
return err;
 
 err_radio_off:
-   b43legacy_radio_turn_off(dev);
+   b43legacy_radio_turn_off(dev, 1);
 err_leds_exit:
b43legacy_leds_exit(dev);
b43legacy_gpio_cleanup(dev);
@@ -2154,8 +2154,7 @@ static void b43legacy_periodic_every1sec
radio_hw_enable = b43legacy_is_hw_radio_enabled(dev);
if (unlikely(dev-radio_hw_enable != radio_hw_enable)) {
dev-radio_hw_enable = radio_hw_enable;
-   b43legacyinfo(dev-wl, Radio hardware status changed to %s\n,
-  (radio_hw_enable) ? enabled : disabled);
+   b43legacy_rfkill_toggled(dev, radio_hw_enable);
}
 }
 
@@ -2647,7 +2646,7 @@ static int b43legacy_dev_config(struct i
   physically off. Press the
   button to turn it on.\n);
} else {
-   b43legacy_radio_turn_off(dev);
+   b43legacy_radio_turn_off(dev, 0);
b43legacyinfo(dev-wl, Radio turned off by
   software\n);
}
@@ -3030,11 +3029,15 @@ static void b43legacy_wireless_core_exit
cancel_work_sync(dev-restart_work);
mutex_lock(wl-mutex);
 
+   mutex_unlock(dev-wl-mutex);
+   

[PATCH] b43legacy: Use input-polldev for the rfkill switch

2007-10-10 Thread Larry Finger
This removes the direct call to rfkill on an rfkill event
and replaces it with an input device. This way userspace is also
notified about the event.

This patch is the port to b43legacy of a patch for b43 by Michael Buesch
[EMAIL PROTECTED].

Signed-off-by: Larry Finger [EMAIL PROTECTED]
---

John,

As with the two previous LED-related patches, this is meant to be applied to
the everything branch of wireless-2.6.

Larry
---

 drivers/net/wireless/b43legacy/Kconfig  |2
 drivers/net/wireless/b43legacy/main.c   |   49 ++-
 drivers/net/wireless/b43legacy/rfkill.c |  135 +++-
 drivers/net/wireless/b43legacy/rfkill.h |   26 --
 4 files changed, 109 insertions(+), 103 deletions(-)

Index: wireless-2.6/drivers/net/wireless/b43legacy/Kconfig
===
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/Kconfig
+++ wireless-2.6/drivers/net/wireless/b43legacy/Kconfig
@@ -43,7 +43,7 @@ config B43LEGACY_LEDS
 # RFKILL support
 config B43LEGACY_RFKILL
bool
-   depends on B43LEGACY  RFKILL
+   depends on B43LEGACY  RFKILL  RFKILL_INPUT  INPUT_POLLDEV
default y
 
 config B43LEGACY_DEBUG
Index: wireless-2.6/drivers/net/wireless/b43legacy/main.c
===
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/main.c
+++ wireless-2.6/drivers/net/wireless/b43legacy/main.c
@@ -1975,21 +1975,6 @@ static void b43legacy_mgmtframe_txantenn
  B43legacy_SHM_SH_PRPHYCTL, tmp);
 }
 
-/* Returns TRUE, if the radio is enabled in hardware. */
-static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
-{
-   if (dev-phy.rev = 3) {
-   if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
-  B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
-   return 1;
-   } else {
-   if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
-B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
-   return 1;
-   }
-   return 0;
-}
-
 /* This is the opposite of b43legacy_chip_init() */
 static void b43legacy_chip_exit(struct b43legacy_wldev *dev)
 {
@@ -2146,32 +2131,18 @@ static void b43legacy_periodic_every15se
b43legacy_phy_xmitpower(dev); /* FIXME: unless scanning? */
 }
 
-static void b43legacy_periodic_every1sec(struct b43legacy_wldev *dev)
-{
-   bool radio_hw_enable;
-
-   /* check if radio hardware enabled status changed */
-   radio_hw_enable = b43legacy_is_hw_radio_enabled(dev);
-   if (unlikely(dev-radio_hw_enable != radio_hw_enable)) {
-   dev-radio_hw_enable = radio_hw_enable;
-   b43legacy_rfkill_toggled(dev, radio_hw_enable);
-   }
-}
-
 static void do_periodic_work(struct b43legacy_wldev *dev)
 {
unsigned int state;
 
state = dev-periodic_state;
-   if (state % 120 == 0)
+   if (state % 8 == 0)
b43legacy_periodic_every120sec(dev);
-   if (state % 60 == 0)
+   if (state % 4 == 0)
b43legacy_periodic_every60sec(dev);
-   if (state % 30 == 0)
+   if (state % 2 == 0)
b43legacy_periodic_every30sec(dev);
-   if (state % 15 == 0)
-   b43legacy_periodic_every15sec(dev);
-   b43legacy_periodic_every1sec(dev);
+   b43legacy_periodic_every15sec(dev);
 }
 
 /* Estimate a Badness value based on the periodic work
@@ -2182,13 +2153,11 @@ static int estimate_periodic_work_badnes
 {
int badness = 0;
 
-   if (state % 120 == 0) /* every 120 sec */
+   if (state % 8 == 0) /* every 120 sec */
badness += 10;
-   if (state % 60 == 0) /* every 60 sec */
+   if (state % 4 == 0) /* every 60 sec */
badness += 5;
-   if (state % 30 == 0) /* every 30 sec */
-   badness += 1;
-   if (state % 15 == 0) /* every 15 sec */
+   if (state % 2 == 0) /* every 30 sec */
badness += 1;
 
 #define BADNESS_LIMIT  4
@@ -2246,7 +2215,7 @@ out_requeue:
if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST))
delay = msecs_to_jiffies(50);
else
-   delay = round_jiffies(HZ);
+   delay = round_jiffies(HZ * 15);
queue_delayed_work(dev-wl-hw-workqueue,
   dev-periodic_work, delay);
 out:
@@ -3445,6 +3414,7 @@ static int b43legacy_setup_modes(struct 
 
 static void b43legacy_wireless_core_detach(struct b43legacy_wldev *dev)
 {
+   b43legacy_rfkill_free(dev);
/* We release firmware that late to not be required to re-request
 * is all the time when we reinit the core. */
b43legacy_release_firmware(dev);
@@ -3526,6 +3496,7 @@ static int b43legacy_wireless_core_attac
if (!wl-current_dev)
wl-current_dev = dev;
INIT_WORK(dev-restart_work, 

[PATCH] b43legacy: Rewrite pwork locking

2007-10-10 Thread Larry Finger
Implement much easier and more lightweight locking for
the periodic work. This also removes the last big busywait
loop and replaces it by a sleeping loop.

This patch for b43legacy is patterned aftar the same patch
for b43 by Michael Buesch [EMAIL PROTECTED].

Signed-off-by: Larry Finger [EMAIL PROTECTED]
---

 drivers/net/wireless/b43legacy/main.c |   88 +++---
 1 file changed, 30 insertions(+), 58 deletions(-)

Index: wireless-2.6/drivers/net/wireless/b43legacy/main.c
===
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/main.c
+++ wireless-2.6/drivers/net/wireless/b43legacy/main.c
@@ -1797,6 +1797,7 @@ void b43legacy_mac_enable(struct b43lega
 {
dev-mac_suspended--;
B43legacy_WARN_ON(dev-mac_suspended  0);
+   B43legacy_WARN_ON(irqs_disabled());
if (dev-mac_suspended == 0) {
b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
  b43legacy_read32(dev,
@@ -1808,6 +1809,11 @@ void b43legacy_mac_enable(struct b43lega
b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
b43legacy_power_saving_ctl_bits(dev, -1, -1);
+
+   /* Re-enable IRQs. */
+   spin_lock_irq(dev-wl-irq_lock);
+   b43legacy_interrupt_enable(dev, dev-irq_savedstate);
+   spin_unlock_irq(dev-wl-irq_lock);
}
 }
 
@@ -1817,20 +1823,31 @@ void b43legacy_mac_suspend(struct b43leg
int i;
u32 tmp;
 
+   might_sleep();
+   B43legacy_WARN_ON(irqs_disabled());
B43legacy_WARN_ON(dev-mac_suspended  0);
+
if (dev-mac_suspended == 0) {
+   /* Mask IRQs before suspending MAC. Otherwise
+* the MAC stays busy and won't suspend. */
+   spin_lock_irq(dev-wl-irq_lock);
+   tmp = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+   spin_unlock_irq(dev-wl-irq_lock);
+   b43legacy_synchronize_irq(dev);
+   dev-irq_savedstate = tmp;
+
b43legacy_power_saving_ctl_bits(dev, -1, 1);
b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
  b43legacy_read32(dev,
  B43legacy_MMIO_STATUS_BITFIELD)
   ~B43legacy_SBF_MAC_ENABLED);
b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
-   for (i = 1; i; i--) {
+   for (i = 40; i; i--) {
tmp = b43legacy_read32(dev,
   B43legacy_MMIO_GEN_IRQ_REASON);
if (tmp  B43legacy_IRQ_MAC_SUSPENDED)
goto out;
-   udelay(1);
+   msleep(1);
}
b43legacyerr(dev-wl, MAC suspend failed\n);
}
@@ -2145,81 +2162,36 @@ static void do_periodic_work(struct b43l
b43legacy_periodic_every15sec(dev);
 }
 
-/* Estimate a Badness value based on the periodic work
- * state-machine state. Badness is worse (bigger), if the
- * periodic work will take longer.
+/* Periodic work locking policy:
+ * The whole periodic work handler is protected by
+ * wl-mutex. If another lock is needed somewhere in the
+ * pwork callchain, it's aquired in-place, where it's needed.
  */
-static int estimate_periodic_work_badness(unsigned int state)
-{
-   int badness = 0;
-
-   if (state % 8 == 0) /* every 120 sec */
-   badness += 10;
-   if (state % 4 == 0) /* every 60 sec */
-   badness += 5;
-   if (state % 2 == 0) /* every 30 sec */
-   badness += 1;
-
-#define BADNESS_LIMIT  4
-   return badness;
-}
-
 static void b43legacy_periodic_work_handler(struct work_struct *work)
 {
-   struct b43legacy_wldev *dev =
-container_of(work, struct b43legacy_wldev,
-periodic_work.work);
-   unsigned long flags;
+   struct b43legacy_wldev *dev = container_of(work, struct b43legacy_wldev,
+periodic_work.work);
+   struct b43legacy_wl *wl = dev-wl;
unsigned long delay;
-   u32 savedirqs = 0;
-   int badness;
 
-   mutex_lock(dev-wl-mutex);
+   mutex_lock(wl-mutex);
 
if (unlikely(b43legacy_status(dev) != B43legacy_STAT_STARTED))
goto out;
if (b43legacy_debug(dev, B43legacy_DBG_PWORK_STOP))
goto out_requeue;
 
-   badness = estimate_periodic_work_badness(dev-periodic_state);
-   if (badness  BADNESS_LIMIT) {
-   spin_lock_irqsave(dev-wl-irq_lock, flags);
-   /* Suspend TX as we don't want to transmit packets while
-* we recalibrate the hardware. */
-