aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-3945-led.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-3945-led.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-led.c146
1 files changed, 62 insertions, 84 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
index 8b1528e52d43..6be1fe13fa57 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
@@ -42,14 +42,11 @@
42#include "iwl-3945.h" 42#include "iwl-3945.h"
43#include "iwl-helpers.h" 43#include "iwl-helpers.h"
44 44
45#define IWL_1MB_RATE (128 * 1024)
46#define IWL_LED_THRESHOLD (16)
47#define IWL_MAX_BLINK_TBL (10)
48 45
49static const struct { 46static const struct {
50 u16 brightness; 47 u16 brightness;
51 u8 on_time; 48 u8 on_time;
52 u8 of_time; 49 u8 off_time;
53} blink_tbl[] = 50} blink_tbl[] =
54{ 51{
55 {300, 25, 25}, 52 {300, 25, 25},
@@ -61,9 +58,16 @@ static const struct {
61 {15, 95, 95 }, 58 {15, 95, 95 },
62 {10, 110, 110}, 59 {10, 110, 110},
63 {5, 130, 130}, 60 {5, 130, 130},
64 {0, 167, 167} 61 {0, 167, 167},
62 /*SOLID_ON*/
63 {-1, IWL_LED_SOLID, 0}
65}; 64};
66 65
66#define IWL_1MB_RATE (128 * 1024)
67#define IWL_LED_THRESHOLD (16)
68#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/
69#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
70
67static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv, 71static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv,
68 struct iwl3945_cmd *cmd, 72 struct iwl3945_cmd *cmd,
69 struct sk_buff *skb) 73 struct sk_buff *skb)
@@ -71,6 +75,10 @@ static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv,
71 return 1; 75 return 1;
72} 76}
73 77
78static inline int iwl3945_brightness_to_idx(enum led_brightness brightness)
79{
80 return fls(0x000000FF & (u32)brightness);
81}
74 82
75/* Send led command */ 83/* Send led command */
76static int iwl_send_led_cmd(struct iwl3945_priv *priv, 84static int iwl_send_led_cmd(struct iwl3945_priv *priv,
@@ -81,49 +89,45 @@ static int iwl_send_led_cmd(struct iwl3945_priv *priv,
81 .len = sizeof(struct iwl3945_led_cmd), 89 .len = sizeof(struct iwl3945_led_cmd),
82 .data = led_cmd, 90 .data = led_cmd,
83 .meta.flags = CMD_ASYNC, 91 .meta.flags = CMD_ASYNC,
84 .meta.u.callback = iwl3945_led_cmd_callback 92 .meta.u.callback = iwl3945_led_cmd_callback,
85 }; 93 };
86 94
87 return iwl3945_send_cmd(priv, &cmd); 95 return iwl3945_send_cmd(priv, &cmd);
88} 96}
89 97
90 98
99
91/* Set led on command */ 100/* Set led on command */
92static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) 101static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id,
102 unsigned int idx)
93{ 103{
94 struct iwl3945_led_cmd led_cmd = { 104 struct iwl3945_led_cmd led_cmd = {
95 .id = led_id, 105 .id = led_id,
96 .on = IWL_LED_SOLID,
97 .off = 0,
98 .interval = IWL_DEF_LED_INTRVL 106 .interval = IWL_DEF_LED_INTRVL
99 }; 107 };
108
109 BUG_ON(idx > IWL_MAX_BLINK_TBL);
110
111 led_cmd.on = blink_tbl[idx].on_time;
112 led_cmd.off = blink_tbl[idx].off_time;
113
100 return iwl_send_led_cmd(priv, &led_cmd); 114 return iwl_send_led_cmd(priv, &led_cmd);
101} 115}
102 116
117
118#if 1
103/* Set led on command */ 119/* Set led on command */
104static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, 120static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id)
105 enum led_brightness brightness)
106{ 121{
107 struct iwl3945_led_cmd led_cmd = { 122 struct iwl3945_led_cmd led_cmd = {
108 .id = led_id, 123 .id = led_id,
109 .on = brightness, 124 .on = IWL_LED_SOLID,
110 .off = brightness, 125 .off = 0,
111 .interval = IWL_DEF_LED_INTRVL 126 .interval = IWL_DEF_LED_INTRVL
112 }; 127 };
113 if (brightness == LED_FULL) {
114 led_cmd.on = IWL_LED_SOLID;
115 led_cmd.off = 0;
116 }
117 return iwl_send_led_cmd(priv, &led_cmd); 128 return iwl_send_led_cmd(priv, &led_cmd);
118} 129}
119 130
120/* Set led register off */
121static int iwl3945_led_on_reg(struct iwl3945_priv *priv, int led_id)
122{
123 IWL_DEBUG_LED("led on %d\n", led_id);
124 return iwl3945_led_on(priv, led_id);
125}
126
127/* Set led off command */ 131/* Set led off command */
128static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) 132static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id)
129{ 133{
@@ -136,27 +140,7 @@ static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id)
136 IWL_DEBUG_LED("led off %d\n", led_id); 140 IWL_DEBUG_LED("led off %d\n", led_id);
137 return iwl_send_led_cmd(priv, &led_cmd); 141 return iwl_send_led_cmd(priv, &led_cmd);
138} 142}
139 143#endif
140/* Set led register off */
141static int iwl3945_led_off_reg(struct iwl3945_priv *priv, int led_id)
142{
143 iwl3945_led_off(priv, led_id);
144 return 0;
145}
146
147/* Set led blink command */
148static int iwl3945_led_not_solid(struct iwl3945_priv *priv, int led_id,
149 u8 brightness)
150{
151 struct iwl3945_led_cmd led_cmd = {
152 .id = led_id,
153 .on = brightness,
154 .off = brightness,
155 .interval = IWL_DEF_LED_INTRVL
156 };
157
158 return iwl_send_led_cmd(priv, &led_cmd);
159}
160 144
161 145
162/* 146/*
@@ -206,8 +190,10 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev,
206 led->led_off(priv, IWL_LED_LINK); 190 led->led_off(priv, IWL_LED_LINK);
207 break; 191 break;
208 default: 192 default:
209 if (led->led_pattern) 193 if (led->led_pattern) {
210 led->led_pattern(priv, IWL_LED_LINK, brightness); 194 int idx = iwl3945_brightness_to_idx(brightness);
195 led->led_pattern(priv, IWL_LED_LINK, idx);
196 }
211 break; 197 break;
212 } 198 }
213} 199}
@@ -252,24 +238,20 @@ static int iwl3945_led_register_led(struct iwl3945_priv *priv,
252static inline u8 get_blink_rate(struct iwl3945_priv *priv) 238static inline u8 get_blink_rate(struct iwl3945_priv *priv)
253{ 239{
254 int index; 240 int index;
255 u8 blink_rate; 241 u64 current_tpt = priv->rxtxpackets;
256 242 s64 tpt = current_tpt - priv->led_tpt;
257 if (priv->rxtxpackets < IWL_LED_THRESHOLD)
258 index = 10;
259 else {
260 for (index = 0; index < IWL_MAX_BLINK_TBL; index++) {
261 if (priv->rxtxpackets > (blink_tbl[index].brightness *
262 IWL_1MB_RATE))
263 break;
264 }
265 }
266 /* if 0 frame is transfered */
267 if ((index == IWL_MAX_BLINK_TBL) || !priv->allow_blinking)
268 blink_rate = IWL_LED_SOLID;
269 else
270 blink_rate = blink_tbl[index].on_time;
271 243
272 return blink_rate; 244 if (tpt < 0)
245 tpt = -tpt;
246 priv->led_tpt = current_tpt;
247
248 if (!priv->allow_blinking)
249 index = IWL_MAX_BLINK_TBL;
250 else
251 for (index = 0; index < IWL_MAX_BLINK_TBL; index++)
252 if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE))
253 break;
254 return index;
273} 255}
274 256
275static inline int is_rf_kill(struct iwl3945_priv *priv) 257static inline int is_rf_kill(struct iwl3945_priv *priv)
@@ -285,7 +267,7 @@ static inline int is_rf_kill(struct iwl3945_priv *priv)
285 */ 267 */
286void iwl3945_led_background(struct iwl3945_priv *priv) 268void iwl3945_led_background(struct iwl3945_priv *priv)
287{ 269{
288 u8 blink_rate; 270 u8 blink_idx;
289 271
290 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { 272 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
291 priv->last_blink_time = 0; 273 priv->last_blink_time = 0;
@@ -298,9 +280,10 @@ void iwl3945_led_background(struct iwl3945_priv *priv)
298 280
299 if (!priv->allow_blinking) { 281 if (!priv->allow_blinking) {
300 priv->last_blink_time = 0; 282 priv->last_blink_time = 0;
301 if (priv->last_blink_rate != IWL_LED_SOLID) { 283 if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) {
302 priv->last_blink_rate = IWL_LED_SOLID; 284 priv->last_blink_rate = IWL_SOLID_BLINK_IDX;
303 iwl3945_led_on(priv, IWL_LED_LINK); 285 iwl3945_led_pattern(priv, IWL_LED_LINK,
286 IWL_SOLID_BLINK_IDX);
304 } 287 }
305 return; 288 return;
306 } 289 }
@@ -309,21 +292,14 @@ void iwl3945_led_background(struct iwl3945_priv *priv)
309 msecs_to_jiffies(1000))) 292 msecs_to_jiffies(1000)))
310 return; 293 return;
311 294
312 blink_rate = get_blink_rate(priv); 295 blink_idx = get_blink_rate(priv);
313 296
314 /* call only if blink rate change */ 297 /* call only if blink rate change */
315 if (blink_rate != priv->last_blink_rate) { 298 if (blink_idx != priv->last_blink_rate)
316 if (blink_rate != IWL_LED_SOLID) { 299 iwl3945_led_pattern(priv, IWL_LED_LINK, blink_idx);
317 priv->last_blink_time = jiffies +
318 msecs_to_jiffies(1000);
319 iwl3945_led_not_solid(priv, IWL_LED_LINK, blink_rate);
320 } else {
321 priv->last_blink_time = 0;
322 iwl3945_led_on(priv, IWL_LED_LINK);
323 }
324 }
325 300
326 priv->last_blink_rate = blink_rate; 301 priv->last_blink_time = jiffies;
302 priv->last_blink_rate = blink_idx;
327 priv->rxtxpackets = 0; 303 priv->rxtxpackets = 0;
328} 304}
329 305
@@ -337,6 +313,7 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
337 313
338 priv->last_blink_rate = 0; 314 priv->last_blink_rate = 0;
339 priv->rxtxpackets = 0; 315 priv->rxtxpackets = 0;
316 priv->led_tpt = 0;
340 priv->last_blink_time = 0; 317 priv->last_blink_time = 0;
341 priv->allow_blinking = 0; 318 priv->allow_blinking = 0;
342 319
@@ -344,8 +321,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
344 snprintf(name, sizeof(name), "iwl-%s:radio", 321 snprintf(name, sizeof(name), "iwl-%s:radio",
345 wiphy_name(priv->hw->wiphy)); 322 wiphy_name(priv->hw->wiphy));
346 323
347 priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on_reg; 324 priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on;
348 priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off_reg; 325 priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off;
349 priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; 326 priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
350 327
351 ret = iwl3945_led_register_led(priv, 328 ret = iwl3945_led_register_led(priv,
@@ -364,8 +341,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
364 IWL_LED_TRG_ASSOC, 0, 341 IWL_LED_TRG_ASSOC, 0,
365 name, trigger); 342 name, trigger);
366 /* for assoc always turn led on */ 343 /* for assoc always turn led on */
367 priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on_reg; 344 priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on;
368 priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on_reg; 345 priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on;
369 priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; 346 priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
370 347
371 if (ret) 348 if (ret)
@@ -391,6 +368,7 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
391 trigger = ieee80211_get_tx_led_name(priv->hw); 368 trigger = ieee80211_get_tx_led_name(priv->hw);
392 snprintf(name, sizeof(name), "iwl-%s:TX", 369 snprintf(name, sizeof(name), "iwl-%s:TX",
393 wiphy_name(priv->hw->wiphy)); 370 wiphy_name(priv->hw->wiphy));
371
394 ret = iwl3945_led_register_led(priv, 372 ret = iwl3945_led_register_led(priv,
395 &priv->led[IWL_LED_TRG_TX], 373 &priv->led[IWL_LED_TRG_TX],
396 IWL_LED_TRG_TX, 0, 374 IWL_LED_TRG_TX, 0,