On Saturday 01 November 2008, Johannes Berg wrote: > On Sat, 2008-11-01 at 09:58 +0100, Ivo van Doorn wrote: > > > Could you try this patch? It doesn't matter if it is on top or as a replacement > > of my previous patch. > > > > This patch should also fix suspend/resume handling in general, I suddenly realized > > there was quite a big bug in there regarding EEPROM/CSR handling. > > Now it just hangs at resume, rather than crashing. At suspend it already > logs some MCU errors though. Hmm that is strange, those MCU errors could only come from right before the code I just changed. :S In any case, could you revert the previous patches and try this. This is the same LED patch as before, but I have added the check for set_key() to return immediately when this is called while the module is busy unloading. Ivo --- diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index b362a1c..bbac5c1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -125,6 +125,7 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, int retval; led->led_dev.name = name; + led->led_dev.brightness = LED_OFF; retval = led_classdev_register(device, &led->led_dev); if (retval) { @@ -196,10 +197,12 @@ exit_fail: rt2x00leds_unregister(rt2x00dev); } -static void rt2x00leds_unregister_led(struct rt2x00_led *led) +static inline void rt2x00leds_unregister_led(struct rt2x00_led *led) { + if (!(led->led_dev.flags & LED_SUSPENDED)) + led->led_dev.brightness_set(&led->led_dev, LED_OFF); led_classdev_unregister(&led->led_dev); - led->led_dev.brightness_set(&led->led_dev, LED_OFF); + led->flags &= ~LED_REGISTERED; } @@ -213,22 +216,34 @@ void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev) rt2x00leds_unregister_led(&rt2x00dev->led_radio); } +static inline void rt2x00leds_suspend_led(struct rt2x00_led *led) +{ + led->led_dev.brightness_set(&led->led_dev, LED_OFF); + led_classdev_suspend(&led->led_dev); +} + void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev) { if (rt2x00dev->led_qual.flags & LED_REGISTERED) - led_classdev_suspend(&rt2x00dev->led_qual.led_dev); + rt2x00leds_suspend_led(&rt2x00dev->led_qual); if (rt2x00dev->led_assoc.flags & LED_REGISTERED) - led_classdev_suspend(&rt2x00dev->led_assoc.led_dev); + rt2x00leds_suspend_led(&rt2x00dev->led_assoc); if (rt2x00dev->led_radio.flags & LED_REGISTERED) - led_classdev_suspend(&rt2x00dev->led_radio.led_dev); + rt2x00leds_suspend_led(&rt2x00dev->led_radio); +} + +static inline void rt2x00leds_resume_led(struct rt2x00_led *led) +{ + led_classdev_resume(&led->led_dev); + led->led_dev.brightness_set(&led->led_dev, led->led_dev.brightness); } void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev) { if (rt2x00dev->led_radio.flags & LED_REGISTERED) - led_classdev_resume(&rt2x00dev->led_radio.led_dev); + rt2x00leds_resume_led(&rt2x00dev->led_radio); if (rt2x00dev->led_assoc.flags & LED_REGISTERED) - led_classdev_resume(&rt2x00dev->led_assoc.led_dev); + rt2x00leds_resume_led(&rt2x00dev->led_assoc); if (rt2x00dev->led_qual.flags & LED_REGISTERED) - led_classdev_resume(&rt2x00dev->led_qual.led_dev); + rt2x00leds_resume_led(&rt2x00dev->led_qual); } diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 8fc2315..188f891 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -486,7 +486,9 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key); struct rt2x00lib_crypto crypto; - if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + return 0; + else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) return -EOPNOTSUPP; else if (key->keylen > 32) return -ENOSPC; -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html