Re: [PATCH] b43: Fix MAC control and microcode init

2008-01-25 Thread Johannes Berg

 This also adds a longer delay for waiting for the microcode
 to initialize itself. It seems that the current timeout is sufficient
 on all available devices, but there's no real reason why we shouldn't
 wait for up to one second. Slow embedded devices might exist.

Your decision, but I very much doubt you can make the MAC any slower
than on the old devices, in fact, on new chips it runs considerably
faster I think.

johannes


signature.asc
Description: This is a digitally signed message part
___
Bcm43xx-dev mailing list
Bcm43xx-dev@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev


Re: [PATCH] b43: Fix MAC control and microcode init

2008-01-25 Thread Michael Buesch
On Thursday 24 January 2008 10:13:01 Johannes Berg wrote:
 
  This also adds a longer delay for waiting for the microcode
  to initialize itself. It seems that the current timeout is sufficient
  on all available devices, but there's no real reason why we shouldn't
  wait for up to one second. Slow embedded devices might exist.
 
 Your decision, but I very much doubt you can make the MAC any slower
 than on the old devices, in fact, on new chips it runs considerably
 faster I think.

Ok, well. But the host machine does get faster. In theory we only
gave the microcode 500 microseconds of time to initialize. I think
that is is a pretty tiny timeframe. In practice the time was higher,
because we had a loop that checked MMIO and delayed for 10usec.
Of course this all has overhead. But as machines get faster and faster
I think we can't assume to have more than 500 microseconds of time.

So, increasing the delay to one second doesn't hurt anyone. In
all common cases it will continue after a few milliseconds. That's fine.
Even if there is something going wrong (wrong firmware) you can
interrupt the one second delay by hitting ^C.

I think the specs originally sayed to use a much longer delay than
we were using. But we did use a shorter delay, because in some old
bcm43xx code this ran unter spinlock as far as I remember. So we didn't
want to spin several milliseconds and lockup the system, if something
goes wrong in firmware. These times are gone and now we can sleep
in this part of the code.

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


[PATCH -mm 0/5] b43: Fix suspend/resume deadlock

2008-01-25 Thread Rafael J. Wysocki
Hi,

The following series of patches is intended to fix the suspend/resume deadlock
occuring as a result of unregistering device objects, locked by the PM core,
during suspend/resume cycles by the b43 driver.

In short, the b43 driver is modified to avoid unregistering device objects
during suspend/resume cycles except for the resume code path, in which the
devices are unregistered using the recently introduced suspend-safe method.
For this purpose, it is necessary to introduce the possibility to safely remove
misc devices, leds classdevs and hwrng devices during suspend/resume cycles
(patches 2/5, 4/5, 3/5, respectively).

Please consider for applying.

Thanks,
Rafael

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


[PATCH -mm 1/5] PM: Export device_pm_schedule_removal

2008-01-25 Thread Rafael J. Wysocki
From: Rafael J. Wysocki [EMAIL PROTECTED]

Move the declaration of device_pm_schedule_removal() to device.h
and make it exported, as it will be used directly by some drivers
for unregistering device objects during suspend/resume cycles in a
safe way.

Signed-off-by: Rafael J. Wysocki [EMAIL PROTECTED]
---
 drivers/base/power/main.c  |1 +
 drivers/base/power/power.h |1 -
 include/linux/device.h |6 ++
 3 files changed, 7 insertions(+), 1 deletion(-)

Index: linux-2.6.24-rc8-mm1/drivers/base/power/main.c
===
--- linux-2.6.24-rc8-mm1.orig/drivers/base/power/main.c
+++ linux-2.6.24-rc8-mm1/drivers/base/power/main.c
@@ -129,6 +129,7 @@ void device_pm_schedule_removal(struct d
list_move_tail(dev-power.entry, dpm_destroy);
mutex_unlock(dpm_list_mtx);
 }
+EXPORT_SYMBOL_GPL(device_pm_schedule_removal);
 
 /**
  * pm_sleep_lock - mutual exclusion for registration and suspend
Index: linux-2.6.24-rc8-mm1/include/linux/device.h
===
--- linux-2.6.24-rc8-mm1.orig/include/linux/device.h
+++ linux-2.6.24-rc8-mm1/include/linux/device.h
@@ -532,11 +532,17 @@ extern struct device *device_create(stru
 extern void device_destroy(struct class *cls, dev_t devt);
 #ifdef CONFIG_PM_SLEEP
 extern void destroy_suspended_device(struct class *cls, dev_t devt);
+extern void device_pm_schedule_removal(struct device *);
 #else /* !CONFIG_PM_SLEEP */
 static inline void destroy_suspended_device(struct class *cls, dev_t devt)
 {
device_destroy(cls, devt);
 }
+
+static inline void device_pm_schedule_removal(struct device *dev)
+{
+   device_unregister(dev);
+}
 #endif /* !CONFIG_PM_SLEEP */
 
 /*
Index: linux-2.6.24-rc8-mm1/drivers/base/power/power.h
===
--- linux-2.6.24-rc8-mm1.orig/drivers/base/power/power.h
+++ linux-2.6.24-rc8-mm1/drivers/base/power/power.h
@@ -13,7 +13,6 @@ static inline struct device *to_device(s
 
 extern void device_pm_add(struct device *);
 extern void device_pm_remove(struct device *);
-extern void device_pm_schedule_removal(struct device *);
 extern int pm_sleep_lock(void);
 extern void pm_sleep_unlock(void);
 
___
Bcm43xx-dev mailing list
Bcm43xx-dev@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev


[PATCH -mm 5/5] b43: Avoid unregistering device objects during suspend

2008-01-25 Thread Rafael J. Wysocki
From: Rafael J. Wysocki [EMAIL PROTECTED]

Modify the b43 driver to avoid deadlocking suspend and resume,
which happens as a result of attempting to unregister device objects
locked by the PM core during suspend/resume cycles.  Also, make it
use a suspend-safe method of unregistering device object in the
resume error path.

Signed-off-by: Rafael J. Wysocki [EMAIL PROTECTED]
Acked-by: Michael Buesch [EMAIL PROTECTED]
---
 drivers/net/wireless/b43/b43.h  |1 +
 drivers/net/wireless/b43/leds.c |5 -
 drivers/net/wireless/b43/main.c |   25 -
 3 files changed, 21 insertions(+), 10 deletions(-)

Index: linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/b43.h
===
--- linux-2.6.24-rc8-mm1.orig/drivers/net/wireless/b43/b43.h
+++ linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/b43.h
@@ -706,6 +706,7 @@ struct b43_wldev {
bool short_preamble;/* TRUE, if short preamble is enabled. */
bool short_slot;/* TRUE, if short slot timing is enabled. */
bool radio_hw_enable;   /* saved state of radio hardware enabled state 
*/
+   bool suspend_in_progress;   /* TRUE, if we are in a suspend/resume 
cycle */
 
/* PHY/Radio device. */
struct b43_phy phy;
Index: linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/main.c
===
--- linux-2.6.24-rc8-mm1.orig/drivers/net/wireless/b43/main.c
+++ linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/main.c
@@ -2470,10 +2470,10 @@ static int b43_rng_read(struct hwrng *rn
return (sizeof(u16));
 }
 
-static void b43_rng_exit(struct b43_wl *wl)
+static void b43_rng_exit(struct b43_wl *wl, bool suspended)
 {
if (wl-rng_initialized)
-   hwrng_unregister(wl-rng);
+   __hwrng_unregister(wl-rng, suspended);
 }
 
 static int b43_rng_init(struct b43_wl *wl)
@@ -3298,8 +3298,10 @@ static void b43_wireless_core_exit(struc
return;
b43_set_status(dev, B43_STAT_UNINIT);
 
-   b43_leds_exit(dev);
-   b43_rng_exit(dev-wl);
+   if (!dev-suspend_in_progress) {
+   b43_leds_exit(dev);
+   b43_rng_exit(dev-wl, false);
+   }
b43_pio_free(dev);
b43_dma_free(dev);
b43_chip_exit(dev);
@@ -3420,11 +3422,13 @@ static int b43_wireless_core_init(struct
memset(wl-mac_addr, 0, ETH_ALEN);
b43_upload_card_macaddress(dev);
b43_security_init(dev);
-   b43_rng_init(wl);
+   if (!dev-suspend_in_progress)
+   b43_rng_init(wl);
 
b43_set_status(dev, B43_STAT_INITIALIZED);
 
-   b43_leds_init(dev);
+   if (!dev-suspend_in_progress)
+   b43_leds_init(dev);
 out:
return err;
 
@@ -4024,6 +4028,7 @@ static int b43_suspend(struct ssb_device
b43dbg(wl, Suspending...\n);
 
mutex_lock(wl-mutex);
+   wldev-suspend_in_progress = true;
wldev-suspend_init_status = b43_status(wldev);
if (wldev-suspend_init_status = B43_STAT_STARTED)
b43_wireless_core_stop(wldev);
@@ -4055,15 +4060,17 @@ static int b43_resume(struct ssb_device 
if (wldev-suspend_init_status = B43_STAT_STARTED) {
err = b43_wireless_core_start(wldev);
if (err) {
+   b43_leds_exit(wldev);
+   b43_rng_exit(wldev-wl, true);
b43_wireless_core_exit(wldev);
b43err(wl, Resume failed at core start\n);
goto out;
}
}
-   mutex_unlock(wl-mutex);
-
b43dbg(wl, Device resumed.\n);
-  out:
+ out:
+   wldev-suspend_in_progress = false;
+   mutex_unlock(wl-mutex);
return err;
 }
 
Index: linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/leds.c
===
--- linux-2.6.24-rc8-mm1.orig/drivers/net/wireless/b43/leds.c
+++ linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/leds.c
@@ -116,7 +116,10 @@ static void b43_unregister_led(struct b4
 {
if (!led-dev)
return;
-   led_classdev_unregister(led-led_dev);
+   if (led-dev-suspend_in_progress)
+   led_classdev_unregister_suspended(led-led_dev);
+   else
+   led_classdev_unregister(led-led_dev);
b43_led_turn_off(led-dev, led-index, led-activelow);
led-dev = NULL;
 }
___
Bcm43xx-dev mailing list
Bcm43xx-dev@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev


[PATCH -mm 3/5] HWRNG: Add possibility to remove hwrng devices during suspend/resume

2008-01-25 Thread Rafael J. Wysocki
From: Rafael J. Wysocki [EMAIL PROTECTED]

Make it possible to unregister a Hardware Random Number Generator
device object in a safe way during a suspend/resume cycle.

Signed-off-by: Rafael J. Wysocki [EMAIL PROTECTED]
Acked-by: Michael Buesch [EMAIL PROTECTED]
---
 drivers/char/hw_random/core.c |   10 +-
 include/linux/hw_random.h |   10 +-
 2 files changed, 14 insertions(+), 6 deletions(-)

Index: linux-2.6.24-rc8-mm1/drivers/char/hw_random/core.c
===
--- linux-2.6.24-rc8-mm1.orig/drivers/char/hw_random/core.c
+++ linux-2.6.24-rc8-mm1/drivers/char/hw_random/core.c
@@ -234,11 +234,11 @@ static DEVICE_ATTR(rng_available, S_IRUG
   NULL);
 
 
-static void unregister_miscdev(void)
+static void unregister_miscdev(bool suspended)
 {
device_remove_file(rng_miscdev.this_device, dev_attr_rng_available);
device_remove_file(rng_miscdev.this_device, dev_attr_rng_current);
-   misc_deregister(rng_miscdev);
+   __misc_deregister(rng_miscdev, suspended);
 }
 
 static int register_miscdev(void)
@@ -313,7 +313,7 @@ out:
 }
 EXPORT_SYMBOL_GPL(hwrng_register);
 
-void hwrng_unregister(struct hwrng *rng)
+void __hwrng_unregister(struct hwrng *rng, bool suspended)
 {
int err;
 
@@ -332,11 +332,11 @@ void hwrng_unregister(struct hwrng *rng)
}
}
if (list_empty(rng_list))
-   unregister_miscdev();
+   unregister_miscdev(suspended);
 
mutex_unlock(rng_mutex);
 }
-EXPORT_SYMBOL_GPL(hwrng_unregister);
+EXPORT_SYMBOL_GPL(__hwrng_unregister);
 
 
 MODULE_DESCRIPTION(H/W Random Number Generator (RNG) driver);
Index: linux-2.6.24-rc8-mm1/include/linux/hw_random.h
===
--- linux-2.6.24-rc8-mm1.orig/include/linux/hw_random.h
+++ linux-2.6.24-rc8-mm1/include/linux/hw_random.h
@@ -44,7 +44,15 @@ struct hwrng {
 /** Register a new Hardware Random Number Generator driver. */
 extern int hwrng_register(struct hwrng *rng);
 /** Unregister a Hardware Random Number Generator driver. */
-extern void hwrng_unregister(struct hwrng *rng);
+extern void __hwrng_unregister(struct hwrng *rng, bool suspended);
+static inline void hwrng_unregister(struct hwrng *rng)
+{
+   __hwrng_unregister(rng, false);
+}
+static inline void hwrng_unregister_suspended(struct hwrng *rng)
+{
+   __hwrng_unregister(rng, true);
+}
 
 #endif /* __KERNEL__ */
 #endif /* LINUX_HWRANDOM_H_ */

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


[PATCH -mm 4/5] Leds: Add possibility to remove leds classdevs during suspend/resume

2008-01-25 Thread Rafael J. Wysocki
From: Rafael J. Wysocki [EMAIL PROTECTED]

Make it possible to unregister a led classdev object in a safe way
during a suspend/resume cycle.

Signed-off-by: Rafael J. Wysocki [EMAIL PROTECTED]
---
 drivers/leds/led-class.c |   13 +
 include/linux/leds.h |   10 +-
 2 files changed, 18 insertions(+), 5 deletions(-)

Index: linux-2.6.24-rc8-mm1/drivers/leds/led-class.c
===
--- linux-2.6.24-rc8-mm1.orig/drivers/leds/led-class.c
+++ linux-2.6.24-rc8-mm1/drivers/leds/led-class.c
@@ -137,12 +137,14 @@ err_out:
 EXPORT_SYMBOL_GPL(led_classdev_register);
 
 /**
- * led_classdev_unregister - unregisters a object of led_properties class.
+ * __led_classdev_unregister - unregisters a object of led_properties class.
  * @led_cdev: the led device to unregister
+ * @suspended: indicates whether system-wide suspend or resume is in progress
  *
  * Unregisters a previously registered via led_classdev_register object.
  */
-void led_classdev_unregister(struct led_classdev *led_cdev)
+void __led_classdev_unregister(struct led_classdev *led_cdev,
+ bool suspended)
 {
device_remove_file(led_cdev-dev, dev_attr_brightness);
 #ifdef CONFIG_LEDS_TRIGGERS
@@ -153,13 +155,16 @@ void led_classdev_unregister(struct led_
up_write(led_cdev-trigger_lock);
 #endif
 
-   device_unregister(led_cdev-dev);
+   if (suspended)
+   device_pm_schedule_removal(led_cdev-dev);
+   else
+   device_unregister(led_cdev-dev);
 
down_write(leds_list_lock);
list_del(led_cdev-node);
up_write(leds_list_lock);
 }
-EXPORT_SYMBOL_GPL(led_classdev_unregister);
+EXPORT_SYMBOL_GPL(__led_classdev_unregister);
 
 static int __init leds_init(void)
 {
Index: linux-2.6.24-rc8-mm1/include/linux/leds.h
===
--- linux-2.6.24-rc8-mm1.orig/include/linux/leds.h
+++ linux-2.6.24-rc8-mm1/include/linux/leds.h
@@ -59,7 +59,15 @@ struct led_classdev {
 
 extern int led_classdev_register(struct device *parent,
 struct led_classdev *led_cdev);
-extern void led_classdev_unregister(struct led_classdev *led_cdev);
+extern void __led_classdev_unregister(struct led_classdev *led_cdev, bool sus);
+static inline void led_classdev_unregister(struct led_classdev *lcd)
+{
+   __led_classdev_unregister(lcd, false);
+}
+static inline void led_classdev_unregister_suspended(struct led_classdev *lcd)
+{
+   __led_classdev_unregister(lcd, true);
+}
 extern void led_classdev_suspend(struct led_classdev *led_cdev);
 extern void led_classdev_resume(struct led_classdev *led_cdev);
 

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


[PATCH -mm 2/5] Misc: Add possibility to remove misc devices during suspend/resume

2008-01-25 Thread Rafael J. Wysocki
From: Rafael J. Wysocki [EMAIL PROTECTED]

Make it possible to unregister a misc device object in a safe way
during a suspend/resume cycle.

Signed-off-by: Rafael J. Wysocki [EMAIL PROTECTED]
---
 drivers/char/misc.c|   13 +
 include/linux/miscdevice.h |   10 +-
 2 files changed, 18 insertions(+), 5 deletions(-)

Index: linux-2.6.24-rc8-mm1/include/linux/miscdevice.h
===
--- linux-2.6.24-rc8-mm1.orig/include/linux/miscdevice.h
+++ linux-2.6.24-rc8-mm1/include/linux/miscdevice.h
@@ -43,7 +43,15 @@ struct miscdevice  {
 };
 
 extern int misc_register(struct miscdevice * misc);
-extern int misc_deregister(struct miscdevice * misc);
+extern int __misc_deregister(struct miscdevice *misc, bool suspended);
+static inline int misc_deregister(struct miscdevice *misc)
+{
+   return __misc_deregister(misc, false);
+}
+static inline int misc_deregister_suspended(struct miscdevice *misc)
+{
+   return __misc_deregister(misc, true);
+}
 
 #define MODULE_ALIAS_MISCDEV(minor)\
MODULE_ALIAS(char-major- __stringify(MISC_MAJOR)  \
Index: linux-2.6.24-rc8-mm1/drivers/char/misc.c
===
--- linux-2.6.24-rc8-mm1.orig/drivers/char/misc.c
+++ linux-2.6.24-rc8-mm1/drivers/char/misc.c
@@ -232,8 +232,9 @@ int misc_register(struct miscdevice * mi
 }
 
 /**
- * misc_deregister - unregister a miscellaneous device
+ * __misc_deregister - unregister a miscellaneous device
  * @misc: device to unregister
+ * @suspended: to be set if the function is used during suspend/resume
  *
  * Unregister a miscellaneous device that was previously
  * successfully registered with misc_register(). Success
@@ -241,7 +242,7 @@ int misc_register(struct miscdevice * mi
  * indicates an error.
  */
 
-int misc_deregister(struct miscdevice * misc)
+int __misc_deregister(struct miscdevice *misc, bool suspended)
 {
int i = misc-minor;
 
@@ -250,7 +251,11 @@ int misc_deregister(struct miscdevice * 
 
mutex_lock(misc_mtx);
list_del(misc-list);
-   device_destroy(misc_class, MKDEV(MISC_MAJOR, misc-minor));
+   if (suspended)
+   destroy_suspended_device(misc_class,
+   MKDEV(MISC_MAJOR, misc-minor));
+   else
+   device_destroy(misc_class, MKDEV(MISC_MAJOR, misc-minor));
if (i  DYNAMIC_MINORS  i0) {
misc_minors[i3] = ~(1  (misc-minor  7));
}
@@ -259,7 +264,7 @@ int misc_deregister(struct miscdevice * 
 }
 
 EXPORT_SYMBOL(misc_register);
-EXPORT_SYMBOL(misc_deregister);
+EXPORT_SYMBOL(__misc_deregister);
 
 static int __init misc_init(void)
 {

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


Re: [PATCH -mm 5/5] b43: Avoid unregistering device objects during suspend

2008-01-25 Thread Michael Buesch
On Friday 25 January 2008 08:47:46 Pavel Machek wrote:
 On Fri 2008-01-25 01:37:33, Rafael J. Wysocki wrote:
  From: Rafael J. Wysocki [EMAIL PROTECTED]
  
  Modify the b43 driver to avoid deadlocking suspend and resume,
  which happens as a result of attempting to unregister device objects
  locked by the PM core during suspend/resume cycles.  Also, make it
  use a suspend-safe method of unregistering device object in the
  resume error path.
  
  Signed-off-by: Rafael J. Wysocki [EMAIL PROTECTED]
  Acked-by: Michael Buesch [EMAIL PROTECTED]
 
 Maybe we should have global suspend_in_progress (or maybe system_state
 == suspending?) and automatically switch to schedule_removal() while
 it is set?
 

That would be great, from my perspective :)

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


[PATCH stable 3/3] b43: Fix dma-slot resource leakage

2008-01-25 Thread Michael Buesch
This fixes four resource leakages.
In any error path we must deallocate the DMA frame slots we
previously allocated by request_slot().
This is done by storing the ring pointers before doing any ring
allocation and restoring the old pointers in case of an error.

Signed-off-by: Michael Buesch [EMAIL PROTECTED]

---

This patch is upstream inside of the netdev tree.


Index: linux-2.6.24/drivers/net/wireless/b43/dma.c
===
--- linux-2.6.24.orig/drivers/net/wireless/b43/dma.c2008-01-25 
11:48:31.0 +0100
+++ linux-2.6.24/drivers/net/wireless/b43/dma.c 2008-01-25 11:48:34.0 
+0100
@@ -1106,7 +1106,7 @@ static int dma_tx_fragment(struct b43_dm
 {
const struct b43_dma_ops *ops = ring-ops;
u8 *header;
-   int slot;
+   int slot, old_top_slot, old_used_slots;
int err;
struct b43_dmadesc_generic *desc;
struct b43_dmadesc_meta *meta;
@@ -1116,6 +1116,9 @@ static int dma_tx_fragment(struct b43_dm
 #define SLOTS_PER_PACKET  2
B43_WARN_ON(skb_shinfo(skb)-nr_frags);
 
+   old_top_slot = ring-current_slot;
+   old_used_slots = ring-used_slots;
+
/* Get a slot for the header. */
slot = request_slot(ring);
desc = ops-idx2desc(ring, slot, meta_hdr);
@@ -1125,13 +1128,19 @@ static int dma_tx_fragment(struct b43_dm
err = b43_generate_txhdr(ring-dev, header,
   skb-data, skb-len, ctl,
   generate_cookie(ring, slot));
-   if (unlikely(err))
+   if (unlikely(err)) {
+   ring-current_slot = old_top_slot;
+   ring-used_slots = old_used_slots;
return err;
+   }
 
meta_hdr-dmaaddr = map_descbuffer(ring, (unsigned char *)header,
   sizeof(struct b43_txhdr_fw4), 1);
-   if (dma_mapping_error(meta_hdr-dmaaddr))
+   if (dma_mapping_error(meta_hdr-dmaaddr)) {
+   ring-current_slot = old_top_slot;
+   ring-used_slots = old_used_slots;
return -EIO;
+   }
ops-fill_descriptor(ring, desc, meta_hdr-dmaaddr,
 sizeof(struct b43_txhdr_fw4), 1, 0, 0);
 
@@ -1149,6 +1158,8 @@ static int dma_tx_fragment(struct b43_dm
if (dma_mapping_error(meta-dmaaddr)) {
bounce_skb = __dev_alloc_skb(skb-len, GFP_ATOMIC | GFP_DMA);
if (!bounce_skb) {
+   ring-current_slot = old_top_slot;
+   ring-used_slots = old_used_slots;
err = -ENOMEM;
goto out_unmap_hdr;
}
@@ -1159,6 +1170,8 @@ static int dma_tx_fragment(struct b43_dm
meta-skb = skb;
meta-dmaaddr = map_descbuffer(ring, skb-data, skb-len, 1);
if (dma_mapping_error(meta-dmaaddr)) {
+   ring-current_slot = old_top_slot;
+   ring-used_slots = old_used_slots;
err = -EIO;
goto out_free_bounce;
}
___
Bcm43xx-dev mailing list
Bcm43xx-dev@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev


[PATCH stable 1/3] b43: Fix suspend/resume

2008-01-25 Thread Michael Buesch
This patch makes suspend/resume work with the b43 driver.
We must not overwrite the MAC addresses in the init function, as this
would also overwrite the MAC on resume. With an all-zero MAC the device
firmware is not able to ACK any received packets anymore.
Fix this by moving the initializion stuff that must be done on init but
not on resume to the start function.
Also zero out filter_flags to make sure we don't have some flags
from a previous instance for a tiny timeframe until mac80211 reconfigures
them.

Signed-off-by: Michael Buesch [EMAIL PROTECTED]

---

This patch is upstream inside of the netdev tree.


Index: linux-2.6.24/drivers/net/wireless/b43/main.c
===
--- linux-2.6.24.orig/drivers/net/wireless/b43/main.c   2008-01-25 
11:48:26.0 +0100
+++ linux-2.6.24/drivers/net/wireless/b43/main.c2008-01-25 
11:48:28.0 +0100
@@ -3395,8 +3395,6 @@ static int b43_wireless_core_init(struct
b43_bluetooth_coext_enable(dev);
 
ssb_bus_powerup(bus, 1);/* Enable dynamic PCTL */
-   memset(wl-bssid, 0, ETH_ALEN);
-   memset(wl-mac_addr, 0, ETH_ALEN);
b43_upload_card_macaddress(dev);
b43_security_init(dev);
b43_rng_init(wl);
@@ -3493,6 +3491,13 @@ static int b43_start(struct ieee80211_hw
int did_init = 0;
int err = 0;
 
+   /* Kill all old instance specific information to make sure
+* the card won't use it in the short timeframe between start
+* and mac80211 reconfiguring it. */
+   memset(wl-bssid, 0, ETH_ALEN);
+   memset(wl-mac_addr, 0, ETH_ALEN);
+   wl-filter_flags = 0;
+
/* First register RFkill.
 * LEDs that are registered later depend on it. */
b43_rfkill_init(dev);
___
Bcm43xx-dev mailing list
Bcm43xx-dev@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev


[PATCH stable 2/3] b43: Drop packets we are not able to encrypt

2008-01-25 Thread Michael Buesch
We must drop any packets we are not able to encrypt.
We must not send them unencrypted or with an all-zero-key (which
basically is the same as unencrypted, from a security point of view).

This might only trigger shortly after resume before mac80211 reassociated
and reconfigured the keys.

It is safe to drop these packets, as the association they belong to
is not guaranteed anymore anyway.
This is a security fix in the sense that it prevents information leakage.

Signed-off-by: Michael Buesch [EMAIL PROTECTED]

---

This patch is upstream inside of the netdev tree.


Index: linux-2.6.24/drivers/net/wireless/b43/dma.c
===
--- linux-2.6.24.orig/drivers/net/wireless/b43/dma.c2008-01-25 
11:48:25.0 +0100
+++ linux-2.6.24/drivers/net/wireless/b43/dma.c 2008-01-25 11:48:31.0 
+0100
@@ -1122,9 +1122,11 @@ static int dma_tx_fragment(struct b43_dm
memset(meta_hdr, 0, sizeof(*meta_hdr));
 
header = (ring-txhdr_cache[slot * sizeof(struct b43_txhdr_fw4)]);
-   b43_generate_txhdr(ring-dev, header,
+   err = b43_generate_txhdr(ring-dev, header,
   skb-data, skb-len, ctl,
   generate_cookie(ring, slot));
+   if (unlikely(err))
+   return err;
 
meta_hdr-dmaaddr = map_descbuffer(ring, (unsigned char *)header,
   sizeof(struct b43_txhdr_fw4), 1);
@@ -1219,6 +1221,13 @@ int b43_dma_tx(struct b43_wldev *dev,
B43_WARN_ON(ring-stopped);
 
err = dma_tx_fragment(ring, skb, ctl);
+   if (unlikely(err == -ENOKEY)) {
+   /* Drop this packet, as we don't have the encryption key
+* anymore and must not transmit it unencrypted. */
+   dev_kfree_skb_any(skb);
+   err = 0;
+   goto out_unlock;
+   }
if (unlikely(err)) {
b43err(dev-wl, DMA tx mapping failure\n);
goto out_unlock;
Index: linux-2.6.24/drivers/net/wireless/b43/xmit.c
===
--- linux-2.6.24.orig/drivers/net/wireless/b43/xmit.c   2008-01-25 
11:48:25.0 +0100
+++ linux-2.6.24/drivers/net/wireless/b43/xmit.c2008-01-25 
11:48:31.0 +0100
@@ -177,7 +177,7 @@ static u8 b43_calc_fallback_rate(u8 bitr
return 0;
 }
 
-static void generate_txhdr_fw4(struct b43_wldev *dev,
+static int generate_txhdr_fw4(struct b43_wldev *dev,
   struct b43_txhdr_fw4 *txhdr,
   const unsigned char *fragment_data,
   unsigned int fragment_len,
@@ -235,7 +235,15 @@ static void generate_txhdr_fw4(struct b4
 
B43_WARN_ON(key_idx = dev-max_nr_keys);
key = (dev-key[key_idx]);
-   B43_WARN_ON(!key-keyconf);
+
+   if (unlikely(!key-keyconf)) {
+   /* This key is invalid. This might only happen
+* in a short timeframe after machine resume before
+* we were able to reconfigure keys.
+* Drop this packet completely. Do not transmit it
+* unencrypted to avoid leaking information. */
+   return -ENOKEY;
+   }
 
/* Hardware appends ICV. */
plcp_fragment_len += txctl-icv_len;
@@ -352,16 +360,18 @@ static void generate_txhdr_fw4(struct b4
txhdr-mac_ctl = cpu_to_le32(mac_ctl);
txhdr-phy_ctl = cpu_to_le16(phy_ctl);
txhdr-extra_ft = extra_ft;
+
+   return 0;
 }
 
-void b43_generate_txhdr(struct b43_wldev *dev,
+int b43_generate_txhdr(struct b43_wldev *dev,
u8 * txhdr,
const unsigned char *fragment_data,
unsigned int fragment_len,
const struct ieee80211_tx_control *txctl, u16 cookie)
 {
-   generate_txhdr_fw4(dev, (struct b43_txhdr_fw4 *)txhdr,
-  fragment_data, fragment_len, txctl, cookie);
+   return generate_txhdr_fw4(dev, (struct b43_txhdr_fw4 *)txhdr,
+ fragment_data, fragment_len, txctl, cookie);
 }
 
 static s8 b43_rssi_postprocess(struct b43_wldev *dev,
Index: linux-2.6.24/drivers/net/wireless/b43/xmit.h
===
--- linux-2.6.24.orig/drivers/net/wireless/b43/xmit.h   2008-01-25 
11:48:25.0 +0100
+++ linux-2.6.24/drivers/net/wireless/b43/xmit.h2008-01-25 
11:48:31.0 +0100
@@ -82,7 +82,7 @@ struct b43_txhdr_fw4 {
 #define  B43_TX4_PHY_ANT1  0x0100  /* Use antenna 1 */
 #define  B43_TX4_PHY_ANTLAST   0x0300  /* Use last used antenna */
 
-void b43_generate_txhdr(struct b43_wldev *dev,
+int b43_generate_txhdr(struct b43_wldev *dev,
u8 * txhdr,

Re: [PATCH -mm 5/5] b43: Avoid unregistering device objects during suspend

2008-01-25 Thread Rafael J. Wysocki
On Friday, 25 of January 2008, Michael Buesch wrote:
 On Friday 25 January 2008 08:47:46 Pavel Machek wrote:
  On Fri 2008-01-25 01:37:33, Rafael J. Wysocki wrote:
   From: Rafael J. Wysocki [EMAIL PROTECTED]
   
   Modify the b43 driver to avoid deadlocking suspend and resume,
   which happens as a result of attempting to unregister device objects
   locked by the PM core during suspend/resume cycles.  Also, make it
   use a suspend-safe method of unregistering device object in the
   resume error path.
   
   Signed-off-by: Rafael J. Wysocki [EMAIL PROTECTED]
   Acked-by: Michael Buesch [EMAIL PROTECTED]
  
  Maybe we should have global suspend_in_progress (or maybe system_state
  == suspending?) and automatically switch to schedule_removal() while
  it is set?
  
 
 That would be great, from my perspective :)

Let's see how many drivers are going to need that.  If there's more than a
couple, it will certainly make sense to have a global variable like this.

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


[PATCH stable 4/4] b43legacy: fix DMA slot resource leakage

2008-01-25 Thread Stefano Brivio
This fixes four resource leakages.
In any error path we must deallocate the DMA frame slots we
previously allocated by request_slot().
This is done by storing the ring pointers before doing any ring
allocation and restoring the old pointers in case of an error.

This patch by Michael Buesch has been ported to b43legacy.

Cc: Michael Buesch [EMAIL PROTECTED]
Signed-off-by: Stefano Brivio [EMAIL PROTECTED]
---
Index: linux-2.6.24/drivers/net/wireless/b43legacy/dma.c
===
--- linux-2.6.24.orig/drivers/net/wireless/b43legacy/dma.c
+++ linux-2.6.24/drivers/net/wireless/b43legacy/dma.c
@@ -1164,7 +1164,7 @@ static int dma_tx_fragment(struct b43leg
 {
const struct b43legacy_dma_ops *ops = ring-ops;
u8 *header;
-   int slot;
+   int slot, old_top_slot, old_used_slots;
int err;
struct b43legacy_dmadesc_generic *desc;
struct b43legacy_dmadesc_meta *meta;
@@ -1174,6 +1174,9 @@ static int dma_tx_fragment(struct b43leg
 #define SLOTS_PER_PACKET  2
B43legacy_WARN_ON(skb_shinfo(skb)-nr_frags != 0);
 
+   old_top_slot = ring-current_slot;
+   old_used_slots = ring-used_slots;
+
/* Get a slot for the header. */
slot = request_slot(ring);
desc = ops-idx2desc(ring, slot, meta_hdr);
@@ -1184,8 +1187,11 @@ static int dma_tx_fragment(struct b43leg
err = b43legacy_generate_txhdr(ring-dev, header,
 skb-data, skb-len, ctl,
 generate_cookie(ring, slot));
-   if (unlikely(err))
+   if (unlikely(err)) {
+   ring-current_slot = old_top_slot;
+   ring-used_slots = old_used_slots;
return err;
+   }
 
meta_hdr-dmaaddr = map_descbuffer(ring, (unsigned char *)header,
   sizeof(struct b43legacy_txhdr_fw3), 1);
@@ -1208,6 +1214,8 @@ static int dma_tx_fragment(struct b43leg
if (dma_mapping_error(meta-dmaaddr)) {
bounce_skb = __dev_alloc_skb(skb-len, GFP_ATOMIC | GFP_DMA);
if (!bounce_skb) {
+   ring-current_slot = old_top_slot;
+   ring-used_slots = old_used_slots;
err = -ENOMEM;
goto out_unmap_hdr;
}
@@ -1218,6 +1226,8 @@ static int dma_tx_fragment(struct b43leg
meta-skb = skb;
meta-dmaaddr = map_descbuffer(ring, skb-data, skb-len, 1);
if (dma_mapping_error(meta-dmaaddr)) {
+   ring-current_slot = old_top_slot;
+   ring-used_slots = old_used_slots;
err = -EIO;
goto out_free_bounce;
}


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


[PATCH stable 2/4] b43legacy: fix suspend/resume

2008-01-25 Thread Stefano Brivio
This patch makes suspend/resume work with the b43legacy driver.
We must not overwrite the MAC addresses in the init function, as this
would also overwrite the MAC on resume. With an all-zero MAC the device
firmware is not able to ACK any received packets anymore.
Fix this by moving the initializion stuff that must be done on init but
not on resume to the start function.
Also zero out filter_flags to make sure we don't have some flags
from a previous instance for a tiny timeframe until mac80211 reconfigures
them.

This patch by Michael Buesch has been ported to b43legacy.

Cc: Michael Buesch [EMAIL PROTECTED]
Signed-off-by: Stefano Brivio [EMAIL PROTECTED]
---
Index: linux-2.6.24/drivers/net/wireless/b43legacy/main.c
===
--- linux-2.6.24.orig/drivers/net/wireless/b43legacy/main.c
+++ linux-2.6.24/drivers/net/wireless/b43legacy/main.c
@@ -3215,8 +3215,6 @@ static int b43legacy_wireless_core_init(
b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
 
ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
-   memset(wl-bssid, 0, ETH_ALEN);
-   memset(wl-mac_addr, 0, ETH_ALEN);
b43legacy_upload_card_macaddress(dev);
b43legacy_security_init(dev);
b43legacy_rng_init(wl);
@@ -3311,6 +3309,13 @@ static int b43legacy_start(struct ieee80
int did_init = 0;
int err = 0;
 
+   /* Kill all old instance specific information to make sure
+* the card won't use it in the short timeframe between start
+* and mac80211 reconfiguring it. */
+   memset(wl-bssid, 0, ETH_ALEN);
+   memset(wl-mac_addr, 0, ETH_ALEN);
+   wl-filter_flags = 0;
+
mutex_lock(wl-mutex);
 
if (b43legacy_status(dev)  B43legacy_STAT_INITIALIZED) {


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


[PATCH stable 1/4] b43legacy: fix PIO crash

2008-01-25 Thread Stefano Brivio
Fix the crash reported below, which seems to happen on bcm4306 rev. 2 devices
only while using PIO:

Oops:  [#1] PREEMPT
Modules linked in: b43(F) rfkill(F) led_class(F) input_polldev(F) arc4 
b43legacy mac80211 cfg80211 i915 drm snd_seq_oss snd_seq_midi_event snd_seq 
snd_seq_device ohci1394 ieee1394 ssb pcmcia snd_intel8x0m ehci_hcd uhci_hcd 
evdev

Pid: 0, comm: swapper Tainted: GF   (2.6.24st3 #2)
EIP: 0060:[f90f667b] EFLAGS: 00010002 CPU: 0
EIP is at b43legacy_pio_handle_txstatus+0xbb/0x210 [b43legacy]
EAX: 049b EBX: f11f8044 ECX: 0001 EDX: 
ESI: f1ff8000 EDI:  EBP: f11f8040 ESP: c04f4ef4
 DS: 007b ES: 007b FS:  GS:  SS: 0068
Process swapper (pid: 0, ti=c04f4000 task=c0488300 task.ti=c04b8000)
Stack: f90f2788 c05009f0 c0500900 10f7 f1053823 c04f4f24 dfb8e800 0003
   f1368000 0007 0296 f90f1975 1000 010c0800 0100 0007
   f90f6391 f11f8000 0082 c04f4f4a  4fd0 10f7 8c061000
Call Trace:
 [f90f2788] b43legacy_debugfs_log_txstat+0x48/0xb0 [b43legacy]
 [f90f1975] b43legacy_handle_hwtxstatus+0x75/0x80 [b43legacy]
 [f90f6391] b43legacy_pio_rx+0x201/0x280 [b43legacy]
 [f90e4fa3] b43legacy_interrupt_tasklet+0x2e3/0x870 [b43legacy]
 [c0123567] tasklet_action+0x27/0x60
 [c01237b4] __do_softirq+0x54/0xb0
 [c010686b] do_softirq+0x7b/0xe0
 [c01457c0] handle_level_irq+0x0/0x110
 [c01457c0] handle_level_irq+0x0/0x110
 [c0123758] irq_exit+0x38/0x40
 [c0106953] do_IRQ+0x83/0xd0
 [c011812f] __update_rq_clock+0x4f/0x180
 [c0104b4f] common_interrupt+0x23/0x28
 [c011007b] wakeup_code+0x7b/0xde
 [c02b1039] acpi_processor_idle+0x24a/0x3c9
 [c01025c7] cpu_idle+0x47/0x80
 [c04b9ad5] start_kernel+0x205/0x290
 [c04b9360] unknown_bootoption+0x0/0x1f0
 ===
Code: 0f 00 00 81 fb ff 00 00 00 0f 87 36 01 00 00 8d 04 db 85 ff 8d 6c c6 40 
8d 5d 04 0f 85 ef 00 00 00 fe 4e 0e 0f b7 46 0c 8b 53 04 8b 4a 50 29 c8 83 e8 
52 66 89 46 0c 8b 54 24 14 80 7a 0b 00 74
EIP: [f90f667b] b43legacy_pio_handle_txstatus+0xbb/0x210 [b43legacy] SS:ESP 
0068:c04f4ef4
Kernel panic - not syncing: Fatal exception in interrupt

Signed-off-by: Stefano Brivio [EMAIL PROTECTED]
---
Index: linux-2.6.24/drivers/net/wireless/b43legacy/pio.c
===
--- linux-2.6.24.orig/drivers/net/wireless/b43legacy/pio.c
+++ linux-2.6.24/drivers/net/wireless/b43legacy/pio.c
@@ -486,6 +486,9 @@ void b43legacy_pio_handle_txstatus(struc
queue = parse_cookie(dev, status-cookie, packet);
B43legacy_WARN_ON(!queue);
 
+   if (!packet-skb)
+   return;
+
queue-tx_devq_packets--;
queue-tx_devq_used -= (packet-skb-len +
sizeof(struct b43legacy_txhdr_fw3));


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


[PATCH stable 3/4] b43legacy: drop packets we are not able to encrypt

2008-01-25 Thread Stefano Brivio
We must drop any packets we are not able to encrypt.
We must not send them unencrypted or with an all-zero-key (which
basically is the same as unencrypted, from a security point of view).

This might only trigger shortly after resume before mac80211 reassociated
and reconfigured the keys.

It is safe to drop these packets, as the association they belong to
is not guaranteed anymore anyway.
This is a security fix in the sense that it prevents information leakage.

This patch by Michael Buesch has been ported to b43legacy.

Cc: Michael Buesch [EMAIL PROTECTED]
Signed-off-by: Stefano Brivio [EMAIL PROTECTED]
---
Index: linux-2.6.24/drivers/net/wireless/b43legacy/dma.c
===
--- linux-2.6.24.orig/drivers/net/wireless/b43legacy/dma.c
+++ linux-2.6.24/drivers/net/wireless/b43legacy/dma.c
@@ -1181,9 +1181,11 @@ static int dma_tx_fragment(struct b43leg
 
header = (ring-txhdr_cache[slot * sizeof(
   struct b43legacy_txhdr_fw3)]);
-   b43legacy_generate_txhdr(ring-dev, header,
+   err = b43legacy_generate_txhdr(ring-dev, header,
 skb-data, skb-len, ctl,
 generate_cookie(ring, slot));
+   if (unlikely(err))
+   return err;
 
meta_hdr-dmaaddr = map_descbuffer(ring, (unsigned char *)header,
   sizeof(struct b43legacy_txhdr_fw3), 1);
@@ -1282,6 +1284,13 @@ int b43legacy_dma_tx(struct b43legacy_wl
B43legacy_BUG_ON(ring-stopped);
 
err = dma_tx_fragment(ring, skb, ctl);
+   if (unlikely(err == -ENOKEY)) {
+   /* Drop this packet, as we don't have the encryption key
+* anymore and must not transmit it unencrypted. */
+   dev_kfree_skb_any(skb);
+   err = 0;
+   goto out_unlock;
+   }
if (unlikely(err)) {
b43legacyerr(dev-wl, DMA tx mapping failure\n);
goto out_unlock;
Index: linux-2.6.24/drivers/net/wireless/b43legacy/pio.c
===
--- linux-2.6.24.orig/drivers/net/wireless/b43legacy/pio.c
+++ linux-2.6.24/drivers/net/wireless/b43legacy/pio.c
@@ -181,7 +181,7 @@ union txhdr_union {
struct b43legacy_txhdr_fw3 txhdr_fw3;
 };
 
-static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
+static int pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
  struct sk_buff *skb,
  struct b43legacy_pio_txpacket *packet,
  size_t txhdr_size)
@@ -189,14 +189,17 @@ static void pio_tx_write_fragment(struct
union txhdr_union txhdr_data;
u8 *txhdr = NULL;
unsigned int octets;
+   int err;
 
txhdr = (u8 *)(txhdr_data.txhdr_fw3);
 
B43legacy_WARN_ON(skb_shinfo(skb)-nr_frags != 0);
-   b43legacy_generate_txhdr(queue-dev,
+   err = b43legacy_generate_txhdr(queue-dev,
 txhdr, skb-data, skb-len,
 packet-txstat.control,
 generate_cookie(queue, packet));
+   if (err)
+   return err;
 
tx_start(queue);
octets = skb-len + txhdr_size;
@@ -204,6 +207,8 @@ static void pio_tx_write_fragment(struct
octets--;
tx_data(queue, txhdr, (u8 *)skb-data, octets);
tx_complete(queue, skb);
+
+   return 0;
 }
 
 static void free_txpacket(struct b43legacy_pio_txpacket *packet,
@@ -226,6 +231,7 @@ static int pio_tx_packet(struct b43legac
struct b43legacy_pioqueue *queue = packet-queue;
struct sk_buff *skb = packet-skb;
u16 octets;
+   int err;
 
octets = (u16)skb-len + sizeof(struct b43legacy_txhdr_fw3);
if (queue-tx_devq_size  octets) {
@@ -247,8 +253,14 @@ static int pio_tx_packet(struct b43legac
if (queue-tx_devq_used + octets  queue-tx_devq_size)
return -EBUSY;
/* Now poke the device. */
-   pio_tx_write_fragment(queue, skb, packet,
+   err = pio_tx_write_fragment(queue, skb, packet,
  sizeof(struct b43legacy_txhdr_fw3));
+   if (unlikely(err == -ENOKEY)) {
+   /* Drop this packet, as we don't have the encryption key
+* anymore and must not transmit it unencrypted. */
+   free_txpacket(packet, 1);
+   return 0;
+   }
 
/* Account for the packet size.
 * (We must not overflow the device TX queue)
Index: linux-2.6.24/drivers/net/wireless/b43legacy/xmit.c
===
--- linux-2.6.24.orig/drivers/net/wireless/b43legacy/xmit.c
+++ linux-2.6.24/drivers/net/wireless/b43legacy/xmit.c
@@ -181,7 +181,7 @@ static u8 b43legacy_calc_fallback_rate(u
return 0;
 }
 
-static void