aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/p54/p54.h25
-rw-r--r--drivers/net/wireless/p54/p54common.c124
-rw-r--r--drivers/net/wireless/p54/p54common.h7
3 files changed, 143 insertions, 13 deletions
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index 071cbe965377..2dda5fe418b6 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -14,6 +14,10 @@
14 * published by the Free Software Foundation. 14 * published by the Free Software Foundation.
15 */ 15 */
16 16
17#ifdef CONFIG_MAC80211_LEDS
18#include <linux/leds.h>
19#endif /* CONFIG_MAC80211_LEDS */
20
17enum p54_control_frame_types { 21enum p54_control_frame_types {
18 P54_CONTROL_TYPE_SETUP = 0, 22 P54_CONTROL_TYPE_SETUP = 0,
19 P54_CONTROL_TYPE_SCAN, 23 P54_CONTROL_TYPE_SCAN,
@@ -112,6 +116,21 @@ enum fw_state {
112 FW_STATE_RESETTING, 116 FW_STATE_RESETTING,
113}; 117};
114 118
119#ifdef CONFIG_MAC80211_LEDS
120
121#define P54_LED_MAX_NAME_LEN 31
122
123struct p54_led_dev {
124 struct ieee80211_hw *hw_dev;
125 struct led_classdev led_dev;
126 char name[P54_LED_MAX_NAME_LEN + 1];
127
128 unsigned int index;
129 unsigned int registered;
130};
131
132#endif /* CONFIG_MAC80211_LEDS */
133
115struct p54_common { 134struct p54_common {
116 struct ieee80211_hw *hw; 135 struct ieee80211_hw *hw;
117 u32 rx_start; 136 u32 rx_start;
@@ -157,6 +176,12 @@ struct p54_common {
157 struct completion eeprom_comp; 176 struct completion eeprom_comp;
158 u8 privacy_caps; 177 u8 privacy_caps;
159 u8 rx_keycache_size; 178 u8 rx_keycache_size;
179 /* LED management */
180 #ifdef CONFIG_MAC80211_LEDS
181 struct p54_led_dev assoc_led;
182 struct p54_led_dev tx_led;
183 #endif /* CONFIG_MAC80211_LEDS */
184 u16 softled_state; /* bit field of glowing LEDs */
160}; 185};
161 186
162int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); 187int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index f76365057172..93abe49f4bde 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -21,6 +21,9 @@
21#include <linux/etherdevice.h> 21#include <linux/etherdevice.h>
22 22
23#include <net/mac80211.h> 23#include <net/mac80211.h>
24#ifdef CONFIG_MAC80211_LEDS
25#include <linux/leds.h>
26#endif /* CONFIG_MAC80211_LEDS */
24 27
25#include "p54.h" 28#include "p54.h"
26#include "p54common.h" 29#include "p54common.h"
@@ -1871,7 +1874,7 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell)
1871 return -EINVAL; 1874 return -EINVAL;
1872} 1875}
1873 1876
1874static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act) 1877static int p54_set_leds(struct ieee80211_hw *dev)
1875{ 1878{
1876 struct p54_common *priv = dev->priv; 1879 struct p54_common *priv = dev->priv;
1877 struct sk_buff *skb; 1880 struct sk_buff *skb;
@@ -1882,11 +1885,11 @@ static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
1882 if (!skb) 1885 if (!skb)
1883 return -ENOMEM; 1886 return -ENOMEM;
1884 1887
1885 led = (struct p54_led *)skb_put(skb, sizeof(*led)); 1888 led = (struct p54_led *) skb_put(skb, sizeof(*led));
1886 led->mode = cpu_to_le16(mode); 1889 led->flags = cpu_to_le16(0x0003);
1887 led->led_permanent = cpu_to_le16(link); 1890 led->mask[0] = led->mask[1] = cpu_to_le16(priv->softled_state);
1888 led->led_temporary = cpu_to_le16(act); 1891 led->delay[0] = cpu_to_le16(1);
1889 led->duration = cpu_to_le16(1000); 1892 led->delay[1] = cpu_to_le16(0);
1890 priv->tx(dev, skb); 1893 priv->tx(dev, skb);
1891 return 0; 1894 return 0;
1892} 1895}
@@ -2070,6 +2073,9 @@ static int p54_start(struct ieee80211_hw *dev)
2070 2073
2071 queue_delayed_work(dev->workqueue, &priv->work, 0); 2074 queue_delayed_work(dev->workqueue, &priv->work, 0);
2072 2075
2076 priv->softled_state = 0;
2077 err = p54_set_leds(dev);
2078
2073out: 2079out:
2074 mutex_unlock(&priv->conf_mutex); 2080 mutex_unlock(&priv->conf_mutex);
2075 return err; 2081 return err;
@@ -2082,6 +2088,9 @@ static void p54_stop(struct ieee80211_hw *dev)
2082 2088
2083 mutex_lock(&priv->conf_mutex); 2089 mutex_lock(&priv->conf_mutex);
2084 priv->mode = NL80211_IFTYPE_UNSPECIFIED; 2090 priv->mode = NL80211_IFTYPE_UNSPECIFIED;
2091 priv->softled_state = 0;
2092 p54_set_leds(dev);
2093
2085 cancel_delayed_work_sync(&priv->work); 2094 cancel_delayed_work_sync(&priv->work);
2086 if (priv->cached_beacon) 2095 if (priv->cached_beacon)
2087 p54_tx_cancel(dev, priv->cached_beacon); 2096 p54_tx_cancel(dev, priv->cached_beacon);
@@ -2119,7 +2128,6 @@ static int p54_add_interface(struct ieee80211_hw *dev,
2119 2128
2120 memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); 2129 memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
2121 p54_setup_mac(dev); 2130 p54_setup_mac(dev);
2122 p54_set_leds(dev, 1, 0, 0);
2123 mutex_unlock(&priv->conf_mutex); 2131 mutex_unlock(&priv->conf_mutex);
2124 return 0; 2132 return 0;
2125} 2133}
@@ -2199,8 +2207,6 @@ static int p54_config_interface(struct ieee80211_hw *dev,
2199 goto out; 2207 goto out;
2200 } 2208 }
2201 2209
2202 ret = p54_set_leds(dev, 1, !is_multicast_ether_addr(priv->bssid), 0);
2203
2204out: 2210out:
2205 mutex_unlock(&priv->conf_mutex); 2211 mutex_unlock(&priv->conf_mutex);
2206 return ret; 2212 return ret;
@@ -2419,6 +2425,96 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
2419 return 0; 2425 return 0;
2420} 2426}
2421 2427
2428#ifdef CONFIG_MAC80211_LEDS
2429static void p54_led_brightness_set(struct led_classdev *led_dev,
2430 enum led_brightness brightness)
2431{
2432 struct p54_led_dev *led = container_of(led_dev, struct p54_led_dev,
2433 led_dev);
2434 struct ieee80211_hw *dev = led->hw_dev;
2435 struct p54_common *priv = dev->priv;
2436 int err;
2437
2438 /* Don't toggle the LED, when the device is down. */
2439 if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
2440 return ;
2441
2442 if (brightness != LED_OFF)
2443 priv->softled_state |= BIT(led->index);
2444 else
2445 priv->softled_state &= ~BIT(led->index);
2446
2447 err = p54_set_leds(dev);
2448 if (err && net_ratelimit())
2449 printk(KERN_ERR "%s: failed to update %s LED.\n",
2450 wiphy_name(dev->wiphy), led_dev->name);
2451}
2452
2453static int p54_register_led(struct ieee80211_hw *dev,
2454 struct p54_led_dev *led,
2455 unsigned int led_index,
2456 char *name, char *trigger)
2457{
2458 int err;
2459
2460 if (led->registered)
2461 return -EEXIST;
2462
2463 snprintf(led->name, sizeof(led->name), "p54-%s::%s",
2464 wiphy_name(dev->wiphy), name);
2465 led->hw_dev = dev;
2466 led->index = led_index;
2467 led->led_dev.name = led->name;
2468 led->led_dev.default_trigger = trigger;
2469 led->led_dev.brightness_set = p54_led_brightness_set;
2470
2471 err = led_classdev_register(wiphy_dev(dev->wiphy), &led->led_dev);
2472 if (err)
2473 printk(KERN_ERR "%s: Failed to register %s LED.\n",
2474 wiphy_name(dev->wiphy), name);
2475 else
2476 led->registered = 1;
2477
2478 return err;
2479}
2480
2481static int p54_init_leds(struct ieee80211_hw *dev)
2482{
2483 struct p54_common *priv = dev->priv;
2484 int err;
2485
2486 /*
2487 * TODO:
2488 * Figure out if the EEPROM contains some hints about the number
2489 * of available/programmable LEDs of the device.
2490 * But for now, we can assume that we have two programmable LEDs.
2491 */
2492
2493 err = p54_register_led(dev, &priv->assoc_led, 0, "assoc",
2494 ieee80211_get_assoc_led_name(dev));
2495 if (err)
2496 return err;
2497
2498 err = p54_register_led(dev, &priv->tx_led, 1, "tx",
2499 ieee80211_get_tx_led_name(dev));
2500 if (err)
2501 return err;
2502
2503 err = p54_set_leds(dev);
2504 return err;
2505}
2506
2507static void p54_unregister_leds(struct ieee80211_hw *dev)
2508{
2509 struct p54_common *priv = dev->priv;
2510
2511 if (priv->tx_led.registered)
2512 led_classdev_unregister(&priv->tx_led.led_dev);
2513 if (priv->assoc_led.registered)
2514 led_classdev_unregister(&priv->assoc_led.led_dev);
2515}
2516#endif /* CONFIG_MAC80211_LEDS */
2517
2422static const struct ieee80211_ops p54_ops = { 2518static const struct ieee80211_ops p54_ops = {
2423 .tx = p54_tx, 2519 .tx = p54_tx,
2424 .start = p54_start, 2520 .start = p54_start,
@@ -2499,6 +2595,12 @@ int p54_register_common(struct ieee80211_hw *dev, struct device *pdev)
2499 return err; 2595 return err;
2500 } 2596 }
2501 2597
2598 #ifdef CONFIG_MAC80211_LEDS
2599 err = p54_init_leds(dev);
2600 if (err)
2601 return err;
2602 #endif /* CONFIG_MAC80211_LEDS */
2603
2502 dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy)); 2604 dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy));
2503 return 0; 2605 return 0;
2504} 2606}
@@ -2510,6 +2612,10 @@ void p54_free_common(struct ieee80211_hw *dev)
2510 kfree(priv->iq_autocal); 2612 kfree(priv->iq_autocal);
2511 kfree(priv->output_limit); 2613 kfree(priv->output_limit);
2512 kfree(priv->curve_data); 2614 kfree(priv->curve_data);
2615
2616 #ifdef CONFIG_MAC80211_LEDS
2617 p54_unregister_leds(dev);
2618 #endif /* CONFIG_MAC80211_LEDS */
2513} 2619}
2514EXPORT_SYMBOL_GPL(p54_free_common); 2620EXPORT_SYMBOL_GPL(p54_free_common);
2515 2621
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h
index def23b1f49ec..75ead7a150fc 100644
--- a/drivers/net/wireless/p54/p54common.h
+++ b/drivers/net/wireless/p54/p54common.h
@@ -515,10 +515,9 @@ struct p54_scan_tail_rate {
515} __attribute__ ((packed)); 515} __attribute__ ((packed));
516 516
517struct p54_led { 517struct p54_led {
518 __le16 mode; 518 __le16 flags;
519 __le16 led_temporary; 519 __le16 mask[2];
520 __le16 led_permanent; 520 __le16 delay[2];
521 __le16 duration;
522} __attribute__ ((packed)); 521} __attribute__ ((packed));
523 522
524struct p54_edcf { 523struct p54_edcf {