aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerton Ronaldo Krzesinski <herton@mandriva.com.br>2009-12-09 11:56:13 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-12-10 16:09:51 -0500
commit49d7590ce494a971311ca55d8aaa6ea9a87b108f (patch)
tree07f508f699fd68220f3c13a63c346da3d7566f08
parent512414b0bed0d376ac4d5ec1dd6f0b1a3551febc (diff)
rtl8187: add radio led and fix warnings on suspend
Michael Buesch reports that his rtl8187 gives warnings on suspend ("queueing ieee80211 work while going to suspend" warnings), as rtl8187 can call ieee80211_queue_delayed_work after mac80211 is suspended. This change enhances rtl8187 led code so we can avoid queuing work after mac80211 is suspended: now we register a radio led and make additional checks to ensure led is off/on properly as mac80211 wants. Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br> Tested-by: Larry Finger <Larry.Finger@lwfinger.net> Cc: Stable <stable@vger.kernel.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187.h1
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_leds.c68
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_leds.h2
3 files changed, 50 insertions, 21 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h
index b1a24de0b7b0..6af0f3f71f3a 100644
--- a/drivers/net/wireless/rtl818x/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187.h
@@ -108,6 +108,7 @@ struct rtl8187_priv {
108 struct delayed_work work; 108 struct delayed_work work;
109 struct ieee80211_hw *dev; 109 struct ieee80211_hw *dev;
110#ifdef CONFIG_RTL8187_LEDS 110#ifdef CONFIG_RTL8187_LEDS
111 struct rtl8187_led led_radio;
111 struct rtl8187_led led_tx; 112 struct rtl8187_led led_tx;
112 struct rtl8187_led led_rx; 113 struct rtl8187_led led_rx;
113 struct delayed_work led_on; 114 struct delayed_work led_on;
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c
index cf8a4a40fdf6..ded44c045eb2 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_leds.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c
@@ -105,19 +105,36 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
105 struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led, 105 struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led,
106 led_dev); 106 led_dev);
107 struct ieee80211_hw *hw = led->dev; 107 struct ieee80211_hw *hw = led->dev;
108 struct rtl8187_priv *priv = hw->priv; 108 struct rtl8187_priv *priv;
109 static bool radio_on;
109 110
110 if (brightness == LED_OFF) { 111 if (!hw)
111 ieee80211_queue_delayed_work(hw, &priv->led_off, 0); 112 return;
112 /* The LED is off for 1/20 sec so that it just blinks. */ 113 priv = hw->priv;
113 ieee80211_queue_delayed_work(hw, &priv->led_on, HZ / 20); 114 if (led->is_radio) {
114 } else 115 if (brightness == LED_FULL) {
115 ieee80211_queue_delayed_work(hw, &priv->led_on, 0); 116 ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
117 radio_on = true;
118 } else if (radio_on) {
119 radio_on = false;
120 cancel_delayed_work_sync(&priv->led_on);
121 ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
122 }
123 } else if (radio_on) {
124 if (brightness == LED_OFF) {
125 ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
126 /* The LED is off for 1/20 sec - it just blinks. */
127 ieee80211_queue_delayed_work(hw, &priv->led_on,
128 HZ / 20);
129 } else
130 ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
131 }
116} 132}
117 133
118static int rtl8187_register_led(struct ieee80211_hw *dev, 134static int rtl8187_register_led(struct ieee80211_hw *dev,
119 struct rtl8187_led *led, const char *name, 135 struct rtl8187_led *led, const char *name,
120 const char *default_trigger, u8 ledpin) 136 const char *default_trigger, u8 ledpin,
137 bool is_radio)
121{ 138{
122 int err; 139 int err;
123 struct rtl8187_priv *priv = dev->priv; 140 struct rtl8187_priv *priv = dev->priv;
@@ -128,6 +145,7 @@ static int rtl8187_register_led(struct ieee80211_hw *dev,
128 return -EINVAL; 145 return -EINVAL;
129 led->dev = dev; 146 led->dev = dev;
130 led->ledpin = ledpin; 147 led->ledpin = ledpin;
148 led->is_radio = is_radio;
131 strncpy(led->name, name, sizeof(led->name)); 149 strncpy(led->name, name, sizeof(led->name));
132 150
133 led->led_dev.name = led->name; 151 led->led_dev.name = led->name;
@@ -145,7 +163,11 @@ static int rtl8187_register_led(struct ieee80211_hw *dev,
145 163
146static void rtl8187_unregister_led(struct rtl8187_led *led) 164static void rtl8187_unregister_led(struct rtl8187_led *led)
147{ 165{
166 struct ieee80211_hw *hw = led->dev;
167 struct rtl8187_priv *priv = hw->priv;
168
148 led_classdev_unregister(&led->led_dev); 169 led_classdev_unregister(&led->led_dev);
170 flush_delayed_work(&priv->led_off);
149 led->dev = NULL; 171 led->dev = NULL;
150} 172}
151 173
@@ -183,33 +205,37 @@ void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
183 INIT_DELAYED_WORK(&priv->led_off, led_turn_off); 205 INIT_DELAYED_WORK(&priv->led_off, led_turn_off);
184 206
185 snprintf(name, sizeof(name), 207 snprintf(name, sizeof(name),
208 "rtl8187-%s::radio", wiphy_name(dev->wiphy));
209 err = rtl8187_register_led(dev, &priv->led_radio, name,
210 ieee80211_get_radio_led_name(dev), ledpin, true);
211 if (err)
212 return;
213
214 snprintf(name, sizeof(name),
186 "rtl8187-%s::tx", wiphy_name(dev->wiphy)); 215 "rtl8187-%s::tx", wiphy_name(dev->wiphy));
187 err = rtl8187_register_led(dev, &priv->led_tx, name, 216 err = rtl8187_register_led(dev, &priv->led_tx, name,
188 ieee80211_get_tx_led_name(dev), ledpin); 217 ieee80211_get_tx_led_name(dev), ledpin, false);
189 if (err) 218 if (err)
190 goto error; 219 goto err_tx;
220
191 snprintf(name, sizeof(name), 221 snprintf(name, sizeof(name),
192 "rtl8187-%s::rx", wiphy_name(dev->wiphy)); 222 "rtl8187-%s::rx", wiphy_name(dev->wiphy));
193 err = rtl8187_register_led(dev, &priv->led_rx, name, 223 err = rtl8187_register_led(dev, &priv->led_rx, name,
194 ieee80211_get_rx_led_name(dev), ledpin); 224 ieee80211_get_rx_led_name(dev), ledpin, false);
195 if (!err) { 225 if (!err)
196 ieee80211_queue_delayed_work(dev, &priv->led_on, 0);
197 return; 226 return;
198 } 227
199 /* registration of RX LED failed - unregister TX */ 228 /* registration of RX LED failed - unregister */
200 rtl8187_unregister_led(&priv->led_tx); 229 rtl8187_unregister_led(&priv->led_tx);
201error: 230err_tx:
202 /* If registration of either failed, cancel delayed work */ 231 rtl8187_unregister_led(&priv->led_radio);
203 cancel_delayed_work_sync(&priv->led_off);
204 cancel_delayed_work_sync(&priv->led_on);
205} 232}
206 233
207void rtl8187_leds_exit(struct ieee80211_hw *dev) 234void rtl8187_leds_exit(struct ieee80211_hw *dev)
208{ 235{
209 struct rtl8187_priv *priv = dev->priv; 236 struct rtl8187_priv *priv = dev->priv;
210 237
211 /* turn the LED off before exiting */ 238 rtl8187_unregister_led(&priv->led_radio);
212 ieee80211_queue_delayed_work(dev, &priv->led_off, 0);
213 rtl8187_unregister_led(&priv->led_rx); 239 rtl8187_unregister_led(&priv->led_rx);
214 rtl8187_unregister_led(&priv->led_tx); 240 rtl8187_unregister_led(&priv->led_tx);
215 cancel_delayed_work_sync(&priv->led_off); 241 cancel_delayed_work_sync(&priv->led_off);
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187_leds.h
index a0332027aead..efe8041bdda4 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_leds.h
+++ b/drivers/net/wireless/rtl818x/rtl8187_leds.h
@@ -47,6 +47,8 @@ struct rtl8187_led {
47 u8 ledpin; 47 u8 ledpin;
48 /* The unique name string for this LED device. */ 48 /* The unique name string for this LED device. */
49 char name[RTL8187_LED_MAX_NAME_LEN + 1]; 49 char name[RTL8187_LED_MAX_NAME_LEN + 1];
50 /* If the LED is radio or tx/rx */
51 bool is_radio;
50}; 52};
51 53
52void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); 54void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code);