diff options
author | Christian Lamparter <chunkeey@web.de> | 2009-03-24 22:12:18 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-04-22 16:54:36 -0400 |
commit | dce072580e095d1fb7be59a1be30dc0e8307821b (patch) | |
tree | a4ac9734c5d7703dc02fcd245c61b78dc1c28ff4 | |
parent | cf3a9579f61c643c15c172da0baf5429578b0ba3 (diff) |
p54: more SoftLED updates
This patch hopefully finishes the SoftLED code:
- It adds two more LEDs (rx and radio).
(the FW claims it can support up to 16 LEDs,
but I doubt that any vendor put more than 4 on a board)
- update the LEDs in a _delayed_ workqueue.
No one reported any more crashes.
(see: "PATCH] p54: fix race condition in memory management")
So we can stop burning the mm code.
Signed-off-by: Christian Lamparter <chunkeey@web.de>
Acked-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/p54/p54.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 84 |
2 files changed, 70 insertions, 23 deletions
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 04d95a143383..4499035359a6 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h | |||
@@ -125,6 +125,7 @@ struct p54_led_dev { | |||
125 | struct led_classdev led_dev; | 125 | struct led_classdev led_dev; |
126 | char name[P54_LED_MAX_NAME_LEN + 1]; | 126 | char name[P54_LED_MAX_NAME_LEN + 1]; |
127 | 127 | ||
128 | unsigned int toggled; | ||
128 | unsigned int index; | 129 | unsigned int index; |
129 | unsigned int registered; | 130 | unsigned int registered; |
130 | }; | 131 | }; |
@@ -186,10 +187,10 @@ struct p54_common { | |||
186 | u8 rx_keycache_size; | 187 | u8 rx_keycache_size; |
187 | 188 | ||
188 | /* LED management */ | 189 | /* LED management */ |
189 | #ifdef CONFIG_P54_LEDS | 190 | #ifdef CONFIG_MAC80211_LEDS |
190 | struct p54_led_dev assoc_led; | 191 | struct p54_led_dev leds[4]; |
191 | struct p54_led_dev tx_led; | 192 | struct delayed_work led_work; |
192 | #endif /* CONFIG_P54_LEDS */ | 193 | #endif /* CONFIG_MAC80211_LEDS */ |
193 | u16 softled_state; /* bit field of glowing LEDs */ | 194 | u16 softled_state; /* bit field of glowing LEDs */ |
194 | 195 | ||
195 | /* statistics */ | 196 | /* statistics */ |
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index c8f0232ee5e0..696067e69ee4 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -2088,6 +2088,9 @@ static void p54_stop(struct ieee80211_hw *dev) | |||
2088 | priv->softled_state = 0; | 2088 | priv->softled_state = 0; |
2089 | p54_set_leds(dev); | 2089 | p54_set_leds(dev); |
2090 | 2090 | ||
2091 | #ifdef CONFIG_P54_LEDS | ||
2092 | cancel_delayed_work_sync(&priv->led_work); | ||
2093 | #endif /* CONFIG_P54_LEDS */ | ||
2091 | cancel_delayed_work_sync(&priv->work); | 2094 | cancel_delayed_work_sync(&priv->work); |
2092 | if (priv->cached_beacon) | 2095 | if (priv->cached_beacon) |
2093 | p54_tx_cancel(dev, priv->cached_beacon); | 2096 | p54_tx_cancel(dev, priv->cached_beacon); |
@@ -2421,6 +2424,43 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
2421 | } | 2424 | } |
2422 | 2425 | ||
2423 | #ifdef CONFIG_P54_LEDS | 2426 | #ifdef CONFIG_P54_LEDS |
2427 | static void p54_update_leds(struct work_struct *work) | ||
2428 | { | ||
2429 | struct p54_common *priv = container_of(work, struct p54_common, | ||
2430 | led_work.work); | ||
2431 | int err, i, tmp, blink_delay = 400; | ||
2432 | bool rerun = false; | ||
2433 | |||
2434 | /* Don't toggle the LED, when the device is down. */ | ||
2435 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) | ||
2436 | return ; | ||
2437 | |||
2438 | for (i = 0; i < ARRAY_SIZE(priv->leds); i++) | ||
2439 | if (priv->leds[i].toggled) { | ||
2440 | priv->softled_state |= BIT(i); | ||
2441 | |||
2442 | tmp = 70 + 200 / (priv->leds[i].toggled); | ||
2443 | if (tmp < blink_delay) | ||
2444 | blink_delay = tmp; | ||
2445 | |||
2446 | if (priv->leds[i].led_dev.brightness == LED_OFF) | ||
2447 | rerun = true; | ||
2448 | |||
2449 | priv->leds[i].toggled = | ||
2450 | !!priv->leds[i].led_dev.brightness; | ||
2451 | } else | ||
2452 | priv->softled_state &= ~BIT(i); | ||
2453 | |||
2454 | err = p54_set_leds(priv->hw); | ||
2455 | if (err && net_ratelimit()) | ||
2456 | printk(KERN_ERR "%s: failed to update LEDs.\n", | ||
2457 | wiphy_name(priv->hw->wiphy)); | ||
2458 | |||
2459 | if (rerun) | ||
2460 | queue_delayed_work(priv->hw->workqueue, &priv->led_work, | ||
2461 | msecs_to_jiffies(blink_delay)); | ||
2462 | } | ||
2463 | |||
2424 | static void p54_led_brightness_set(struct led_classdev *led_dev, | 2464 | static void p54_led_brightness_set(struct led_classdev *led_dev, |
2425 | enum led_brightness brightness) | 2465 | enum led_brightness brightness) |
2426 | { | 2466 | { |
@@ -2428,28 +2468,23 @@ static void p54_led_brightness_set(struct led_classdev *led_dev, | |||
2428 | led_dev); | 2468 | led_dev); |
2429 | struct ieee80211_hw *dev = led->hw_dev; | 2469 | struct ieee80211_hw *dev = led->hw_dev; |
2430 | struct p54_common *priv = dev->priv; | 2470 | struct p54_common *priv = dev->priv; |
2431 | int err; | ||
2432 | 2471 | ||
2433 | /* Don't toggle the LED, when the device is down. */ | ||
2434 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) | 2472 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) |
2435 | return ; | 2473 | return ; |
2436 | 2474 | ||
2437 | if (brightness != LED_OFF) | 2475 | if (brightness) { |
2438 | priv->softled_state |= BIT(led->index); | 2476 | led->toggled++; |
2439 | else | 2477 | queue_delayed_work(priv->hw->workqueue, &priv->led_work, |
2440 | priv->softled_state &= ~BIT(led->index); | 2478 | HZ/10); |
2441 | 2479 | } | |
2442 | err = p54_set_leds(dev); | ||
2443 | if (err && net_ratelimit()) | ||
2444 | printk(KERN_ERR "%s: failed to update %s LED.\n", | ||
2445 | wiphy_name(dev->wiphy), led_dev->name); | ||
2446 | } | 2480 | } |
2447 | 2481 | ||
2448 | static int p54_register_led(struct ieee80211_hw *dev, | 2482 | static int p54_register_led(struct ieee80211_hw *dev, |
2449 | struct p54_led_dev *led, | ||
2450 | unsigned int led_index, | 2483 | unsigned int led_index, |
2451 | char *name, char *trigger) | 2484 | char *name, char *trigger) |
2452 | { | 2485 | { |
2486 | struct p54_common *priv = dev->priv; | ||
2487 | struct p54_led_dev *led = &priv->leds[led_index]; | ||
2453 | int err; | 2488 | int err; |
2454 | 2489 | ||
2455 | if (led->registered) | 2490 | if (led->registered) |
@@ -2482,19 +2517,30 @@ static int p54_init_leds(struct ieee80211_hw *dev) | |||
2482 | * TODO: | 2517 | * TODO: |
2483 | * Figure out if the EEPROM contains some hints about the number | 2518 | * Figure out if the EEPROM contains some hints about the number |
2484 | * of available/programmable LEDs of the device. | 2519 | * of available/programmable LEDs of the device. |
2485 | * But for now, we can assume that we have two programmable LEDs. | ||
2486 | */ | 2520 | */ |
2487 | 2521 | ||
2488 | err = p54_register_led(dev, &priv->assoc_led, 0, "assoc", | 2522 | INIT_DELAYED_WORK(&priv->led_work, p54_update_leds); |
2523 | |||
2524 | err = p54_register_led(dev, 0, "assoc", | ||
2489 | ieee80211_get_assoc_led_name(dev)); | 2525 | ieee80211_get_assoc_led_name(dev)); |
2490 | if (err) | 2526 | if (err) |
2491 | return err; | 2527 | return err; |
2492 | 2528 | ||
2493 | err = p54_register_led(dev, &priv->tx_led, 1, "tx", | 2529 | err = p54_register_led(dev, 1, "tx", |
2494 | ieee80211_get_tx_led_name(dev)); | 2530 | ieee80211_get_tx_led_name(dev)); |
2495 | if (err) | 2531 | if (err) |
2496 | return err; | 2532 | return err; |
2497 | 2533 | ||
2534 | err = p54_register_led(dev, 2, "rx", | ||
2535 | ieee80211_get_rx_led_name(dev)); | ||
2536 | if (err) | ||
2537 | return err; | ||
2538 | |||
2539 | err = p54_register_led(dev, 3, "radio", | ||
2540 | ieee80211_get_radio_led_name(dev)); | ||
2541 | if (err) | ||
2542 | return err; | ||
2543 | |||
2498 | err = p54_set_leds(dev); | 2544 | err = p54_set_leds(dev); |
2499 | return err; | 2545 | return err; |
2500 | } | 2546 | } |
@@ -2502,11 +2548,11 @@ static int p54_init_leds(struct ieee80211_hw *dev) | |||
2502 | static void p54_unregister_leds(struct ieee80211_hw *dev) | 2548 | static void p54_unregister_leds(struct ieee80211_hw *dev) |
2503 | { | 2549 | { |
2504 | struct p54_common *priv = dev->priv; | 2550 | struct p54_common *priv = dev->priv; |
2551 | int i; | ||
2505 | 2552 | ||
2506 | if (priv->tx_led.registered) | 2553 | for (i = 0; i < ARRAY_SIZE(priv->leds); i++) |
2507 | led_classdev_unregister(&priv->tx_led.led_dev); | 2554 | if (priv->leds[i].registered) |
2508 | if (priv->assoc_led.registered) | 2555 | led_classdev_unregister(&priv->leds[i].led_dev); |
2509 | led_classdev_unregister(&priv->assoc_led.led_dev); | ||
2510 | } | 2556 | } |
2511 | #endif /* CONFIG_P54_LEDS */ | 2557 | #endif /* CONFIG_P54_LEDS */ |
2512 | 2558 | ||