aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2011-01-21 18:26:39 -0500
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2011-01-21 18:26:39 -0500
commit5ed540aecc2aae92d5c97b9a9306a5bf88ad5574 (patch)
tree0b19e77d0f5ed9ac4d88ab733440d7ea6348ea4e /drivers/net/wireless
parent4a4fdf2e0b9e3534f6ec4f3e7077470bd66924ab (diff)
iwlwifi: use mac80211 throughput trigger
Instead of keeping track of LED blink speed in the driver, use the new mac80211 trigger and link it up with an LED classdev that we now register. This also allows users more flexibility in how they want to have the LED blink or not. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-led.c27
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-led.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-led.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h18
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c201
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.h16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-legacy.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c8
14 files changed, 106 insertions, 240 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index ed424574160e..8994d3072715 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -2,6 +2,10 @@ config IWLWIFI
2 tristate "Intel Wireless Wifi" 2 tristate "Intel Wireless Wifi"
3 depends on PCI && MAC80211 3 depends on PCI && MAC80211
4 select FW_LOADER 4 select FW_LOADER
5 select NEW_LEDS
6 select LEDS_CLASS
7 select LEDS_TRIGGERS
8 select MAC80211_LEDS
5 9
6menu "Debugging Options" 10menu "Debugging Options"
7 depends on IWLWIFI 11 depends on IWLWIFI
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
index abe2b739c4dc..dc7c3a4167a9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
@@ -59,33 +59,6 @@ static int iwl3945_send_led_cmd(struct iwl_priv *priv,
59 return iwl_send_cmd(priv, &cmd); 59 return iwl_send_cmd(priv, &cmd);
60} 60}
61 61
62/* Set led on command */
63static int iwl3945_led_on(struct iwl_priv *priv)
64{
65 struct iwl_led_cmd led_cmd = {
66 .id = IWL_LED_LINK,
67 .on = IWL_LED_SOLID,
68 .off = 0,
69 .interval = IWL_DEF_LED_INTRVL
70 };
71 return iwl3945_send_led_cmd(priv, &led_cmd);
72}
73
74/* Set led off command */
75static int iwl3945_led_off(struct iwl_priv *priv)
76{
77 struct iwl_led_cmd led_cmd = {
78 .id = IWL_LED_LINK,
79 .on = 0,
80 .off = 0,
81 .interval = IWL_DEF_LED_INTRVL
82 };
83 IWL_DEBUG_LED(priv, "led off\n");
84 return iwl3945_send_led_cmd(priv, &led_cmd);
85}
86
87const struct iwl_led_ops iwl3945_led_ops = { 62const struct iwl_led_ops iwl3945_led_ops = {
88 .cmd = iwl3945_send_led_cmd, 63 .cmd = iwl3945_send_led_cmd,
89 .on = iwl3945_led_on,
90 .off = iwl3945_led_off,
91}; 64};
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/drivers/net/wireless/iwlwifi/iwl-agn-led.c
index 1a24946bc203..c1190d965614 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.c
@@ -63,23 +63,11 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
63} 63}
64 64
65/* Set led register off */ 65/* Set led register off */
66static int iwl_led_on_reg(struct iwl_priv *priv) 66void iwlagn_led_enable(struct iwl_priv *priv)
67{ 67{
68 IWL_DEBUG_LED(priv, "led on\n");
69 iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); 68 iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
70 return 0;
71}
72
73/* Set led register off */
74static int iwl_led_off_reg(struct iwl_priv *priv)
75{
76 IWL_DEBUG_LED(priv, "LED Reg off\n");
77 iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF);
78 return 0;
79} 69}
80 70
81const struct iwl_led_ops iwlagn_led_ops = { 71const struct iwl_led_ops iwlagn_led_ops = {
82 .cmd = iwl_send_led_cmd, 72 .cmd = iwl_send_led_cmd,
83 .on = iwl_led_on_reg,
84 .off = iwl_led_off_reg,
85}; 73};
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/drivers/net/wireless/iwlwifi/iwl-agn-led.h
index a594e4fdc6b8..96f323dc5dd6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-led.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.h
@@ -28,5 +28,6 @@
28#define __iwl_agn_led_h__ 28#define __iwl_agn_led_h__
29 29
30extern const struct iwl_led_ops iwlagn_led_ops; 30extern const struct iwl_led_ops iwlagn_led_ops;
31void iwlagn_led_enable(struct iwl_priv *priv);
31 32
32#endif /* __iwl_agn_led_h__ */ 33#endif /* __iwl_agn_led_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 6e80f1070c52..f693293b6bd1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -557,12 +557,10 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
557 557
558 if (changes & BSS_CHANGED_ASSOC) { 558 if (changes & BSS_CHANGED_ASSOC) {
559 if (bss_conf->assoc) { 559 if (bss_conf->assoc) {
560 iwl_led_associate(priv);
561 priv->timestamp = bss_conf->timestamp; 560 priv->timestamp = bss_conf->timestamp;
562 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; 561 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
563 } else { 562 } else {
564 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; 563 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
565 iwl_led_disassociate(priv);
566 } 564 }
567 } 565 }
568 566
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 97657d04aa68..9240abf425c7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -59,6 +59,7 @@
59#include "iwl-sta.h" 59#include "iwl-sta.h"
60#include "iwl-agn-calib.h" 60#include "iwl-agn-calib.h"
61#include "iwl-agn.h" 61#include "iwl-agn.h"
62#include "iwl-agn-led.h"
62 63
63 64
64/****************************************************************************** 65/******************************************************************************
@@ -2741,8 +2742,6 @@ static void iwl_alive_start(struct iwl_priv *priv)
2741 /* At this point, the NIC is initialized and operational */ 2742 /* At this point, the NIC is initialized and operational */
2742 iwl_rf_kill_ct_config(priv); 2743 iwl_rf_kill_ct_config(priv);
2743 2744
2744 iwl_leds_init(priv);
2745
2746 IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); 2745 IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
2747 wake_up_interruptible(&priv->wait_command_queue); 2746 wake_up_interruptible(&priv->wait_command_queue);
2748 2747
@@ -3234,6 +3233,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
3234 priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = 3233 priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
3235 &priv->bands[IEEE80211_BAND_5GHZ]; 3234 &priv->bands[IEEE80211_BAND_5GHZ];
3236 3235
3236 iwl_leds_init(priv);
3237
3237 ret = ieee80211_register_hw(priv->hw); 3238 ret = ieee80211_register_hw(priv->hw);
3238 if (ret) { 3239 if (ret) {
3239 IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); 3240 IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
@@ -3278,7 +3279,7 @@ int iwlagn_mac_start(struct ieee80211_hw *hw)
3278 } 3279 }
3279 } 3280 }
3280 3281
3281 iwl_led_start(priv); 3282 iwlagn_led_enable(priv);
3282 3283
3283out: 3284out:
3284 priv->is_open = 1; 3285 priv->is_open = 1;
@@ -4288,6 +4289,9 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
4288 * we need to set STATUS_EXIT_PENDING bit. 4289 * we need to set STATUS_EXIT_PENDING bit.
4289 */ 4290 */
4290 set_bit(STATUS_EXIT_PENDING, &priv->status); 4291 set_bit(STATUS_EXIT_PENDING, &priv->status);
4292
4293 iwl_leds_exit(priv);
4294
4291 if (priv->mac80211_registered) { 4295 if (priv->mac80211_registered) {
4292 ieee80211_unregister_hw(priv->hw); 4296 ieee80211_unregister_hw(priv->hw);
4293 priv->mac80211_registered = 0; 4297 priv->mac80211_registered = 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index a8d4a936a2e7..8e1b8014ddc1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1676,7 +1676,6 @@ void iwl_clear_traffic_stats(struct iwl_priv *priv)
1676{ 1676{
1677 memset(&priv->tx_stats, 0, sizeof(struct traffic_stats)); 1677 memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
1678 memset(&priv->rx_stats, 0, sizeof(struct traffic_stats)); 1678 memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
1679 priv->led_tpt = 0;
1680} 1679}
1681 1680
1682/* 1681/*
@@ -1769,7 +1768,6 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
1769 stats->data_cnt++; 1768 stats->data_cnt++;
1770 stats->data_bytes += len; 1769 stats->data_bytes += len;
1771 } 1770 }
1772 iwl_leds_background(priv);
1773} 1771}
1774EXPORT_SYMBOL(iwl_update_stats); 1772EXPORT_SYMBOL(iwl_update_stats);
1775#endif 1773#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index a3474376fdbc..bbc5aa7a7f2f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -227,8 +227,6 @@ struct iwl_lib_ops {
227 227
228struct iwl_led_ops { 228struct iwl_led_ops {
229 int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd); 229 int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd);
230 int (*on)(struct iwl_priv *priv);
231 int (*off)(struct iwl_priv *priv);
232}; 230};
233 231
234/* NIC specific ops */ 232/* NIC specific ops */
@@ -494,18 +492,6 @@ static inline void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
494static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx, 492static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
495 __le16 fc, u16 len) 493 __le16 fc, u16 len)
496{ 494{
497 struct traffic_stats *stats;
498
499 if (is_tx)
500 stats = &priv->tx_stats;
501 else
502 stats = &priv->rx_stats;
503
504 if (ieee80211_is_data(fc)) {
505 /* data */
506 stats->data_bytes += len;
507 }
508 iwl_leds_background(priv);
509} 495}
510#endif 496#endif
511/***************************************************** 497/*****************************************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 6fe80b5e7a15..7f11a448d518 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -668,29 +668,6 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
668 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 668 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
669} 669}
670 670
671static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
672 size_t count, loff_t *ppos)
673{
674 struct iwl_priv *priv = file->private_data;
675 int pos = 0;
676 char buf[256];
677 const size_t bufsz = sizeof(buf);
678
679 pos += scnprintf(buf + pos, bufsz - pos,
680 "allow blinking: %s\n",
681 (priv->allow_blinking) ? "True" : "False");
682 if (priv->allow_blinking) {
683 pos += scnprintf(buf + pos, bufsz - pos,
684 "Led blinking rate: %u\n",
685 priv->last_blink_rate);
686 pos += scnprintf(buf + pos, bufsz - pos,
687 "Last blink time: %lu\n",
688 priv->last_blink_time);
689 }
690
691 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
692}
693
694static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, 671static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
695 char __user *user_buf, 672 char __user *user_buf,
696 size_t count, loff_t *ppos) 673 size_t count, loff_t *ppos)
@@ -856,7 +833,6 @@ DEBUGFS_READ_FILE_OPS(channels);
856DEBUGFS_READ_FILE_OPS(status); 833DEBUGFS_READ_FILE_OPS(status);
857DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 834DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
858DEBUGFS_READ_FILE_OPS(qos); 835DEBUGFS_READ_FILE_OPS(qos);
859DEBUGFS_READ_FILE_OPS(led);
860DEBUGFS_READ_FILE_OPS(thermal_throttling); 836DEBUGFS_READ_FILE_OPS(thermal_throttling);
861DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); 837DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
862DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); 838DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
@@ -1725,7 +1701,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
1725 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); 1701 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
1726 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); 1702 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
1727 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); 1703 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
1728 DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR);
1729 if (!priv->cfg->base_params->broken_powersave) { 1704 if (!priv->cfg->base_params->broken_powersave) {
1730 DEBUGFS_ADD_FILE(sleep_level_override, dir_data, 1705 DEBUGFS_ADD_FILE(sleep_level_override, dir_data,
1731 S_IWUSR | S_IRUSR); 1706 S_IWUSR | S_IRUSR);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 2ec680bb8f6d..6dd6508c93b0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -35,6 +35,7 @@
35#include <linux/pci.h> /* for struct pci_device_id */ 35#include <linux/pci.h> /* for struct pci_device_id */
36#include <linux/kernel.h> 36#include <linux/kernel.h>
37#include <linux/wait.h> 37#include <linux/wait.h>
38#include <linux/leds.h>
38#include <net/ieee80211_radiotap.h> 39#include <net/ieee80211_radiotap.h>
39 40
40#include "iwl-eeprom.h" 41#include "iwl-eeprom.h"
@@ -996,7 +997,6 @@ struct reply_agg_tx_error_statistics {
996 u32 unknown; 997 u32 unknown;
997}; 998};
998 999
999#ifdef CONFIG_IWLWIFI_DEBUGFS
1000/* management statistics */ 1000/* management statistics */
1001enum iwl_mgmt_stats { 1001enum iwl_mgmt_stats {
1002 MANAGEMENT_ASSOC_REQ = 0, 1002 MANAGEMENT_ASSOC_REQ = 0,
@@ -1027,16 +1027,13 @@ enum iwl_ctrl_stats {
1027}; 1027};
1028 1028
1029struct traffic_stats { 1029struct traffic_stats {
1030#ifdef CONFIG_IWLWIFI_DEBUGFS
1030 u32 mgmt[MANAGEMENT_MAX]; 1031 u32 mgmt[MANAGEMENT_MAX];
1031 u32 ctrl[CONTROL_MAX]; 1032 u32 ctrl[CONTROL_MAX];
1032 u32 data_cnt; 1033 u32 data_cnt;
1033 u64 data_bytes; 1034 u64 data_bytes;
1034};
1035#else
1036struct traffic_stats {
1037 u64 data_bytes;
1038};
1039#endif 1035#endif
1036};
1040 1037
1041/* 1038/*
1042 * iwl_switch_rxon: "channel switch" structure 1039 * iwl_switch_rxon: "channel switch" structure
@@ -1338,11 +1335,6 @@ struct iwl_priv {
1338 struct iwl_init_alive_resp card_alive_init; 1335 struct iwl_init_alive_resp card_alive_init;
1339 struct iwl_alive_resp card_alive; 1336 struct iwl_alive_resp card_alive;
1340 1337
1341 unsigned long last_blink_time;
1342 u8 last_blink_rate;
1343 u8 allow_blinking;
1344 u64 led_tpt;
1345
1346 u16 active_rate; 1338 u16 active_rate;
1347 1339
1348 u8 start_calib; 1340 u8 start_calib;
@@ -1580,6 +1572,10 @@ struct iwl_priv {
1580 bool hw_ready; 1572 bool hw_ready;
1581 1573
1582 struct iwl_event_log event_log; 1574 struct iwl_event_log event_log;
1575
1576 struct led_classdev led;
1577 unsigned long blink_on, blink_off;
1578 bool led_registered;
1583}; /*iwl_priv */ 1579}; /*iwl_priv */
1584 1580
1585static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) 1581static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 46ccdf406e8e..074ad2275228 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -48,31 +48,19 @@ module_param(led_mode, int, S_IRUGO);
48MODULE_PARM_DESC(led_mode, "0=system default, " 48MODULE_PARM_DESC(led_mode, "0=system default, "
49 "1=On(RF On)/Off(RF Off), 2=blinking"); 49 "1=On(RF On)/Off(RF Off), 2=blinking");
50 50
51static const struct { 51static const struct ieee80211_tpt_blink iwl_blink[] = {
52 u16 tpt; /* Mb/s */ 52 { .throughput = 0 * 1024 - 1, .blink_time = 334 },
53 u8 on_time; 53 { .throughput = 1 * 1024 - 1, .blink_time = 260 },
54 u8 off_time; 54 { .throughput = 5 * 1024 - 1, .blink_time = 220 },
55} blink_tbl[] = 55 { .throughput = 10 * 1024 - 1, .blink_time = 190 },
56{ 56 { .throughput = 20 * 1024 - 1, .blink_time = 170 },
57 {300, 25, 25}, 57 { .throughput = 50 * 1024 - 1, .blink_time = 150 },
58 {200, 40, 40}, 58 { .throughput = 70 * 1024 - 1, .blink_time = 130 },
59 {100, 55, 55}, 59 { .throughput = 100 * 1024 - 1, .blink_time = 110 },
60 {70, 65, 65}, 60 { .throughput = 200 * 1024 - 1, .blink_time = 80 },
61 {50, 75, 75}, 61 { .throughput = 300 * 1024 - 1, .blink_time = 50 },
62 {20, 85, 85},
63 {10, 95, 95},
64 {5, 110, 110},
65 {1, 130, 130},
66 {0, 167, 167},
67 /* SOLID_ON */
68 {-1, IWL_LED_SOLID, 0}
69}; 62};
70 63
71#define IWL_1MB_RATE (128 * 1024)
72#define IWL_LED_THRESHOLD (16)
73#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */
74#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
75
76/* 64/*
77 * Adjust led blink rate to compensate on a MAC Clock difference on every HW 65 * Adjust led blink rate to compensate on a MAC Clock difference on every HW
78 * Led blink rate analysis showed an average deviation of 0% on 3945, 66 * Led blink rate analysis showed an average deviation of 0% on 3945,
@@ -97,133 +85,104 @@ static inline u8 iwl_blink_compensation(struct iwl_priv *priv,
97} 85}
98 86
99/* Set led pattern command */ 87/* Set led pattern command */
100static int iwl_led_pattern(struct iwl_priv *priv, unsigned int idx) 88static int iwl_led_cmd(struct iwl_priv *priv,
89 unsigned long on,
90 unsigned long off)
101{ 91{
102 struct iwl_led_cmd led_cmd = { 92 struct iwl_led_cmd led_cmd = {
103 .id = IWL_LED_LINK, 93 .id = IWL_LED_LINK,
104 .interval = IWL_DEF_LED_INTRVL 94 .interval = IWL_DEF_LED_INTRVL
105 }; 95 };
96 int ret;
106 97
107 BUG_ON(idx > IWL_MAX_BLINK_TBL); 98 if (!test_bit(STATUS_READY, &priv->status))
99 return -EBUSY;
108 100
109 IWL_DEBUG_LED(priv, "Led blink time compensation= %u\n", 101 if (priv->blink_on == on && priv->blink_off == off)
102 return 0;
103
104 IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
110 priv->cfg->base_params->led_compensation); 105 priv->cfg->base_params->led_compensation);
111 led_cmd.on = 106 led_cmd.on = iwl_blink_compensation(priv, on,
112 iwl_blink_compensation(priv, blink_tbl[idx].on_time,
113 priv->cfg->base_params->led_compensation); 107 priv->cfg->base_params->led_compensation);
114 led_cmd.off = 108 led_cmd.off = iwl_blink_compensation(priv, off,
115 iwl_blink_compensation(priv, blink_tbl[idx].off_time,
116 priv->cfg->base_params->led_compensation); 109 priv->cfg->base_params->led_compensation);
117 110
118 return priv->cfg->ops->led->cmd(priv, &led_cmd); 111 ret = priv->cfg->ops->led->cmd(priv, &led_cmd);
112 if (!ret) {
113 priv->blink_on = on;
114 priv->blink_off = off;
115 }
116 return ret;
119} 117}
120 118
121int iwl_led_start(struct iwl_priv *priv) 119static void iwl_led_brightness_set(struct led_classdev *led_cdev,
120 enum led_brightness brightness)
122{ 121{
123 return priv->cfg->ops->led->on(priv); 122 struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
124} 123 unsigned long on = 0;
125EXPORT_SYMBOL(iwl_led_start);
126 124
127int iwl_led_associate(struct iwl_priv *priv) 125 if (brightness > 0)
128{ 126 on = IWL_LED_SOLID;
129 IWL_DEBUG_LED(priv, "Associated\n");
130 if (priv->cfg->led_mode == IWL_LED_BLINK)
131 priv->allow_blinking = 1;
132 priv->last_blink_time = jiffies;
133 127
134 return 0; 128 iwl_led_cmd(priv, on, 0);
135} 129}
136EXPORT_SYMBOL(iwl_led_associate);
137 130
138int iwl_led_disassociate(struct iwl_priv *priv) 131static int iwl_led_blink_set(struct led_classdev *led_cdev,
132 unsigned long *delay_on,
133 unsigned long *delay_off)
139{ 134{
140 priv->allow_blinking = 0; 135 struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
141 136
142 return 0; 137 return iwl_led_cmd(priv, *delay_on, *delay_off);
143} 138}
144EXPORT_SYMBOL(iwl_led_disassociate);
145 139
146/* 140void iwl_leds_init(struct iwl_priv *priv)
147 * calculate blink rate according to last second Tx/Rx activities
148 */
149static int iwl_get_blink_rate(struct iwl_priv *priv)
150{
151 int i;
152 /* count both tx and rx traffic to be able to
153 * handle traffic in either direction
154 */
155 u64 current_tpt = priv->tx_stats.data_bytes +
156 priv->rx_stats.data_bytes;
157 s64 tpt = current_tpt - priv->led_tpt;
158
159 if (tpt < 0) /* wraparound */
160 tpt = -tpt;
161
162 IWL_DEBUG_LED(priv, "tpt %lld current_tpt %llu\n",
163 (long long)tpt,
164 (unsigned long long)current_tpt);
165 priv->led_tpt = current_tpt;
166
167 if (!priv->allow_blinking)
168 i = IWL_MAX_BLINK_TBL;
169 else
170 for (i = 0; i < IWL_MAX_BLINK_TBL; i++)
171 if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE))
172 break;
173
174 IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", i);
175 return i;
176}
177
178/*
179 * this function called from handler. Since setting Led command can
180 * happen very frequent we postpone led command to be called from
181 * REPLY handler so we know ucode is up
182 */
183void iwl_leds_background(struct iwl_priv *priv)
184{ 141{
185 u8 blink_idx; 142 int mode = led_mode;
186 143 int ret;
187 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { 144
188 priv->last_blink_time = 0; 145 if (mode == IWL_LED_DEFAULT)
189 return; 146 mode = priv->cfg->led_mode;
190 } 147
191 if (iwl_is_rfkill(priv)) { 148 priv->led.name = kasprintf(GFP_KERNEL, "%s-led",
192 priv->last_blink_time = 0; 149 wiphy_name(priv->hw->wiphy));
193 return; 150 priv->led.brightness_set = iwl_led_brightness_set;
151 priv->led.blink_set = iwl_led_blink_set;
152 priv->led.max_brightness = 1;
153
154 switch (mode) {
155 case IWL_LED_DEFAULT:
156 WARN_ON(1);
157 break;
158 case IWL_LED_BLINK:
159 priv->led.default_trigger =
160 ieee80211_create_tpt_led_trigger(priv->hw,
161 IEEE80211_TPT_LEDTRIG_FL_CONNECTED,
162 iwl_blink, ARRAY_SIZE(iwl_blink));
163 break;
164 case IWL_LED_RF_STATE:
165 priv->led.default_trigger =
166 ieee80211_get_radio_led_name(priv->hw);
167 break;
194 } 168 }
195 169
196 if (!priv->allow_blinking) { 170 ret = led_classdev_register(&priv->pci_dev->dev, &priv->led);
197 priv->last_blink_time = 0; 171 if (ret) {
198 if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { 172 kfree(priv->led.name);
199 priv->last_blink_rate = IWL_SOLID_BLINK_IDX;
200 iwl_led_pattern(priv, IWL_SOLID_BLINK_IDX);
201 }
202 return; 173 return;
203 } 174 }
204 if (!priv->last_blink_time ||
205 !time_after(jiffies, priv->last_blink_time +
206 msecs_to_jiffies(1000)))
207 return;
208
209 blink_idx = iwl_get_blink_rate(priv);
210 175
211 /* call only if blink rate change */ 176 priv->led_registered = true;
212 if (blink_idx != priv->last_blink_rate)
213 iwl_led_pattern(priv, blink_idx);
214
215 priv->last_blink_time = jiffies;
216 priv->last_blink_rate = blink_idx;
217} 177}
218EXPORT_SYMBOL(iwl_leds_background); 178EXPORT_SYMBOL(iwl_leds_init);
219 179
220void iwl_leds_init(struct iwl_priv *priv) 180void iwl_leds_exit(struct iwl_priv *priv)
221{ 181{
222 priv->last_blink_rate = 0; 182 if (!priv->led_registered)
223 priv->last_blink_time = 0; 183 return;
224 priv->allow_blinking = 0; 184
225 if (led_mode != IWL_LED_DEFAULT && 185 led_classdev_unregister(&priv->led);
226 led_mode != priv->cfg->led_mode) 186 kfree(priv->led.name);
227 priv->cfg->led_mode = led_mode;
228} 187}
229EXPORT_SYMBOL(iwl_leds_init); 188EXPORT_SYMBOL(iwl_leds_exit);
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h
index 9079b33486ef..101eef12b3bb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.h
+++ b/drivers/net/wireless/iwlwifi/iwl-led.h
@@ -31,23 +31,14 @@
31struct iwl_priv; 31struct iwl_priv;
32 32
33#define IWL_LED_SOLID 11 33#define IWL_LED_SOLID 11
34#define IWL_LED_NAME_LEN 31
35#define IWL_DEF_LED_INTRVL cpu_to_le32(1000) 34#define IWL_DEF_LED_INTRVL cpu_to_le32(1000)
36 35
37#define IWL_LED_ACTIVITY (0<<1) 36#define IWL_LED_ACTIVITY (0<<1)
38#define IWL_LED_LINK (1<<1) 37#define IWL_LED_LINK (1<<1)
39 38
40enum led_type {
41 IWL_LED_TRG_TX,
42 IWL_LED_TRG_RX,
43 IWL_LED_TRG_ASSOC,
44 IWL_LED_TRG_RADIO,
45 IWL_LED_TRG_MAX,
46};
47
48/* 39/*
49 * LED mode 40 * LED mode
50 * IWL_LED_DEFAULT: use system default 41 * IWL_LED_DEFAULT: use device default
51 * IWL_LED_RF_STATE: turn LED on/off based on RF state 42 * IWL_LED_RF_STATE: turn LED on/off based on RF state
52 * LED ON = RF ON 43 * LED ON = RF ON
53 * LED OFF = RF OFF 44 * LED OFF = RF OFF
@@ -60,9 +51,6 @@ enum iwl_led_mode {
60}; 51};
61 52
62void iwl_leds_init(struct iwl_priv *priv); 53void iwl_leds_init(struct iwl_priv *priv);
63void iwl_leds_background(struct iwl_priv *priv); 54void iwl_leds_exit(struct iwl_priv *priv);
64int iwl_led_start(struct iwl_priv *priv);
65int iwl_led_associate(struct iwl_priv *priv);
66int iwl_led_disassociate(struct iwl_priv *priv);
67 55
68#endif /* __iwl_leds_h__ */ 56#endif /* __iwl_leds_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.c b/drivers/net/wireless/iwlwifi/iwl-legacy.c
index bb1a742a98a0..927fe37a43ab 100644
--- a/drivers/net/wireless/iwlwifi/iwl-legacy.c
+++ b/drivers/net/wireless/iwlwifi/iwl-legacy.c
@@ -332,7 +332,6 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv,
332{ 332{
333 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); 333 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
334 334
335 iwl_led_disassociate(priv);
336 /* 335 /*
337 * inform the ucode that there is no longer an 336 * inform the ucode that there is no longer an
338 * association and that no more packets should be 337 * association and that no more packets should be
@@ -520,8 +519,6 @@ void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
520 if (bss_conf->assoc) { 519 if (bss_conf->assoc) {
521 priv->timestamp = bss_conf->timestamp; 520 priv->timestamp = bss_conf->timestamp;
522 521
523 iwl_led_associate(priv);
524
525 if (!iwl_is_rfkill(priv)) 522 if (!iwl_is_rfkill(priv))
526 priv->cfg->ops->legacy->post_associate(priv); 523 priv->cfg->ops->legacy->post_associate(priv);
527 } else 524 } else
@@ -545,7 +542,6 @@ void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
545 memcpy(ctx->staging.bssid_addr, 542 memcpy(ctx->staging.bssid_addr,
546 bss_conf->bssid, ETH_ALEN); 543 bss_conf->bssid, ETH_ALEN);
547 memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); 544 memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
548 iwl_led_associate(priv);
549 priv->cfg->ops->legacy->config_ap(priv); 545 priv->cfg->ops->legacy->config_ap(priv);
550 } else 546 } else
551 iwl_set_no_assoc(priv, vif); 547 iwl_set_no_assoc(priv, vif);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 371abbf60eac..9c986f272c2d 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2540,8 +2540,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
2540 2540
2541 iwl3945_reg_txpower_periodic(priv); 2541 iwl3945_reg_txpower_periodic(priv);
2542 2542
2543 iwl_leds_init(priv);
2544
2545 IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); 2543 IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
2546 set_bit(STATUS_READY, &priv->status); 2544 set_bit(STATUS_READY, &priv->status);
2547 wake_up_interruptible(&priv->wait_command_queue); 2545 wake_up_interruptible(&priv->wait_command_queue);
@@ -3170,8 +3168,6 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
3170 * no need to poll the killswitch state anymore */ 3168 * no need to poll the killswitch state anymore */
3171 cancel_delayed_work(&priv->_3945.rfkill_poll); 3169 cancel_delayed_work(&priv->_3945.rfkill_poll);
3172 3170
3173 iwl_led_start(priv);
3174
3175 priv->is_open = 1; 3171 priv->is_open = 1;
3176 IWL_DEBUG_MAC80211(priv, "leave\n"); 3172 IWL_DEBUG_MAC80211(priv, "leave\n");
3177 return 0; 3173 return 0;
@@ -3935,6 +3931,8 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
3935 priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = 3931 priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
3936 &priv->bands[IEEE80211_BAND_5GHZ]; 3932 &priv->bands[IEEE80211_BAND_5GHZ];
3937 3933
3934 iwl_leds_init(priv);
3935
3938 ret = ieee80211_register_hw(priv->hw); 3936 ret = ieee80211_register_hw(priv->hw);
3939 if (ret) { 3937 if (ret) {
3940 IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); 3938 IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
@@ -4194,6 +4192,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
4194 4192
4195 set_bit(STATUS_EXIT_PENDING, &priv->status); 4193 set_bit(STATUS_EXIT_PENDING, &priv->status);
4196 4194
4195 iwl_leds_exit(priv);
4196
4197 if (priv->mac80211_registered) { 4197 if (priv->mac80211_registered) {
4198 ieee80211_unregister_hw(priv->hw); 4198 ieee80211_unregister_hw(priv->hw);
4199 priv->mac80211_registered = 0; 4199 priv->mac80211_registered = 0;