aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2009-03-24 22:12:18 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:54:36 -0400
commitdce072580e095d1fb7be59a1be30dc0e8307821b (patch)
treea4ac9734c5d7703dc02fcd245c61b78dc1c28ff4
parentcf3a9579f61c643c15c172da0baf5429578b0ba3 (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.h9
-rw-r--r--drivers/net/wireless/p54/p54common.c84
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
2427static 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
2424static void p54_led_brightness_set(struct led_classdev *led_dev, 2464static 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
2448static int p54_register_led(struct ieee80211_hw *dev, 2482static 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)
2502static void p54_unregister_leds(struct ieee80211_hw *dev) 2548static 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