Commit 49d7590ce494a971311ca55d8aaa6ea9a87b108f

Authored by Herton Ronaldo Krzesinski
Committed by John W. Linville
1 parent 512414b0be

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>

Showing 3 changed files with 50 additions and 21 deletions Side-by-side Diff

drivers/net/wireless/rtl818x/rtl8187.h
... ... @@ -108,6 +108,7 @@
108 108 struct delayed_work work;
109 109 struct ieee80211_hw *dev;
110 110 #ifdef CONFIG_RTL8187_LEDS
  111 + struct rtl8187_led led_radio;
111 112 struct rtl8187_led led_tx;
112 113 struct rtl8187_led led_rx;
113 114 struct delayed_work led_on;
drivers/net/wireless/rtl818x/rtl8187_leds.c
... ... @@ -105,19 +105,36 @@
105 105 struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led,
106 106 led_dev);
107 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   - ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
112   - /* The LED is off for 1/20 sec so that it just blinks. */
113   - ieee80211_queue_delayed_work(hw, &priv->led_on, HZ / 20);
114   - } else
115   - ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
  111 + if (!hw)
  112 + return;
  113 + priv = hw->priv;
  114 + if (led->is_radio) {
  115 + if (brightness == LED_FULL) {
  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  
118 134 static int rtl8187_register_led(struct ieee80211_hw *dev,
119 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 139 int err;
123 140 struct rtl8187_priv *priv = dev->priv;
... ... @@ -128,6 +145,7 @@
128 145 return -EINVAL;
129 146 led->dev = dev;
130 147 led->ledpin = ledpin;
  148 + led->is_radio = is_radio;
131 149 strncpy(led->name, name, sizeof(led->name));
132 150  
133 151 led->led_dev.name = led->name;
134 152  
... ... @@ -145,7 +163,11 @@
145 163  
146 164 static 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 169 led_classdev_unregister(&led->led_dev);
  170 + flush_delayed_work(&priv->led_off);
149 171 led->dev = NULL;
150 172 }
151 173  
152 174  
153 175  
154 176  
155 177  
156 178  
157 179  
... ... @@ -183,33 +205,37 @@
183 205 INIT_DELAYED_WORK(&priv->led_off, led_turn_off);
184 206  
185 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 215 "rtl8187-%s::tx", wiphy_name(dev->wiphy));
187 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 218 if (err)
190   - goto error;
  219 + goto err_tx;
  220 +
191 221 snprintf(name, sizeof(name),
192 222 "rtl8187-%s::rx", wiphy_name(dev->wiphy));
193 223 err = rtl8187_register_led(dev, &priv->led_rx, name,
194   - ieee80211_get_rx_led_name(dev), ledpin);
195   - if (!err) {
196   - ieee80211_queue_delayed_work(dev, &priv->led_on, 0);
  224 + ieee80211_get_rx_led_name(dev), ledpin, false);
  225 + if (!err)
197 226 return;
198   - }
199   - /* registration of RX LED failed - unregister TX */
  227 +
  228 + /* registration of RX LED failed - unregister */
200 229 rtl8187_unregister_led(&priv->led_tx);
201   -error:
202   - /* If registration of either failed, cancel delayed work */
203   - cancel_delayed_work_sync(&priv->led_off);
204   - cancel_delayed_work_sync(&priv->led_on);
  230 +err_tx:
  231 + rtl8187_unregister_led(&priv->led_radio);
205 232 }
206 233  
207 234 void rtl8187_leds_exit(struct ieee80211_hw *dev)
208 235 {
209 236 struct rtl8187_priv *priv = dev->priv;
210 237  
211   - /* turn the LED off before exiting */
212   - ieee80211_queue_delayed_work(dev, &priv->led_off, 0);
  238 + rtl8187_unregister_led(&priv->led_radio);
213 239 rtl8187_unregister_led(&priv->led_rx);
214 240 rtl8187_unregister_led(&priv->led_tx);
215 241 cancel_delayed_work_sync(&priv->led_off);
drivers/net/wireless/rtl818x/rtl8187_leds.h
... ... @@ -47,6 +47,8 @@
47 47 u8 ledpin;
48 48 /* The unique name string for this LED device. */
49 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  
52 54 void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code);