aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2009-10-16 01:18:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-27 16:48:24 -0400
commite85498b21d0372a00f31ab9f7c0d215c32c9fad5 (patch)
tree1721f68239a613b4d10d63513d71163ca78a1c4d /drivers
parenta82aedbf1b043f7a7474aa9b6d223104ac51827a (diff)
iwmc3200wifi: CT kill support
We set the initial CT (Temperature control) value to 110 degrees. If the chip goes over that threshold, we hard block the device which will turn it down. At the same time we schedule a 30 seconds delayed work that unblock the device (and userspace is supposed to bring it back up), hoping that the chip will have cooled down by then... Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.c11
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.h1
-rw-r--r--drivers/net/wireless/iwmc3200wifi/fw.c2
-rw-r--r--drivers/net/wireless/iwmc3200wifi/iwm.h3
-rw-r--r--drivers/net/wireless/iwmc3200wifi/lmac.h8
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c14
-rw-r--r--drivers/net/wireless/iwmc3200wifi/netdev.c1
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c16
8 files changed, 55 insertions, 1 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c
index 23b52fa2605..aeea909992f 100644
--- a/drivers/net/wireless/iwmc3200wifi/commands.c
+++ b/drivers/net/wireless/iwmc3200wifi/commands.c
@@ -274,6 +274,17 @@ int iwm_send_calib_results(struct iwm_priv *iwm)
274 return ret; 274 return ret;
275} 275}
276 276
277int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit)
278{
279 struct iwm_ct_kill_cfg_cmd cmd;
280
281 cmd.entry_threshold = entry;
282 cmd.exit_threshold = exit;
283
284 return iwm_send_lmac_ptrough_cmd(iwm, REPLY_CT_KILL_CONFIG_CMD, &cmd,
285 sizeof(struct iwm_ct_kill_cfg_cmd), 0);
286}
287
277int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp) 288int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp)
278{ 289{
279 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; 290 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h
index 4e183be1f26..e486f8e8937 100644
--- a/drivers/net/wireless/iwmc3200wifi/commands.h
+++ b/drivers/net/wireless/iwmc3200wifi/commands.h
@@ -396,6 +396,7 @@ int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
396int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested); 396int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
397int iwm_send_calib_results(struct iwm_priv *iwm); 397int iwm_send_calib_results(struct iwm_priv *iwm);
398int iwm_store_rxiq_calib_result(struct iwm_priv *iwm); 398int iwm_store_rxiq_calib_result(struct iwm_priv *iwm);
399int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit);
399 400
400/* UMAC commands */ 401/* UMAC commands */
401int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, 402int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c
index 6b0bcad758c..f02d571b0a1 100644
--- a/drivers/net/wireless/iwmc3200wifi/fw.c
+++ b/drivers/net/wireless/iwmc3200wifi/fw.c
@@ -398,6 +398,8 @@ int iwm_load_fw(struct iwm_priv *iwm)
398 iwm_send_prio_table(iwm); 398 iwm_send_prio_table(iwm);
399 iwm_send_calib_results(iwm); 399 iwm_send_calib_results(iwm);
400 iwm_send_periodic_calib_cfg(iwm, periodic_calib_map); 400 iwm_send_periodic_calib_cfg(iwm, periodic_calib_map);
401 iwm_send_ct_kill_cfg(iwm, iwm->conf.ct_kill_entry,
402 iwm->conf.ct_kill_exit);
401 403
402 return 0; 404 return 0;
403 405
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h
index 1b02a4e2a1a..fe0ab80994d 100644
--- a/drivers/net/wireless/iwmc3200wifi/iwm.h
+++ b/drivers/net/wireless/iwmc3200wifi/iwm.h
@@ -65,6 +65,8 @@ struct iwm_conf {
65 u32 sdio_ior_timeout; 65 u32 sdio_ior_timeout;
66 unsigned long calib_map; 66 unsigned long calib_map;
67 unsigned long expected_calib_map; 67 unsigned long expected_calib_map;
68 u8 ct_kill_entry;
69 u8 ct_kill_exit;
68 bool reset_on_fatal_err; 70 bool reset_on_fatal_err;
69 bool auto_connect; 71 bool auto_connect;
70 bool wimax_not_present; 72 bool wimax_not_present;
@@ -276,6 +278,7 @@ struct iwm_priv {
276 struct iw_statistics wstats; 278 struct iw_statistics wstats;
277 struct delayed_work stats_request; 279 struct delayed_work stats_request;
278 struct delayed_work disconnect; 280 struct delayed_work disconnect;
281 struct delayed_work ct_kill_delay;
279 282
280 struct iwm_debugfs dbg; 283 struct iwm_debugfs dbg;
281 284
diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h
index 6c1a14c4480..a3a79b5e289 100644
--- a/drivers/net/wireless/iwmc3200wifi/lmac.h
+++ b/drivers/net/wireless/iwmc3200wifi/lmac.h
@@ -187,6 +187,14 @@ struct iwm_coex_prio_table_cmd {
187 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ 187 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
188 COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) 188 COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
189 189
190/* CT kill config command */
191struct iwm_ct_kill_cfg_cmd {
192 u32 exit_threshold;
193 u32 reserved;
194 u32 entry_threshold;
195} __attribute__ ((packed));
196
197
190/* LMAC OP CODES */ 198/* LMAC OP CODES */
191#define REPLY_PAD 0x0 199#define REPLY_PAD 0x0
192#define REPLY_ALIVE 0x1 200#define REPLY_ALIVE 0x1
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c
index 170f3370649..3147fe7b513 100644
--- a/drivers/net/wireless/iwmc3200wifi/main.c
+++ b/drivers/net/wireless/iwmc3200wifi/main.c
@@ -63,6 +63,8 @@ static struct iwm_conf def_iwm_conf = {
63 BIT(PHY_CALIBRATE_TX_IQ_CMD) | 63 BIT(PHY_CALIBRATE_TX_IQ_CMD) |
64 BIT(PHY_CALIBRATE_RX_IQ_CMD) | 64 BIT(PHY_CALIBRATE_RX_IQ_CMD) |
65 BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD), 65 BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD),
66 .ct_kill_entry = 110,
67 .ct_kill_exit = 110,
66 .reset_on_fatal_err = 1, 68 .reset_on_fatal_err = 1,
67 .auto_connect = 1, 69 .auto_connect = 1,
68 .wimax_not_present = 0, 70 .wimax_not_present = 0,
@@ -133,6 +135,17 @@ static void iwm_disconnect_work(struct work_struct *work)
133 cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL); 135 cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL);
134} 136}
135 137
138static void iwm_ct_kill_work(struct work_struct *work)
139{
140 struct iwm_priv *iwm =
141 container_of(work, struct iwm_priv, ct_kill_delay.work);
142 struct wiphy *wiphy = iwm_to_wiphy(iwm);
143
144 IWM_INFO(iwm, "CT kill delay timeout\n");
145
146 wiphy_rfkill_set_hw_state(wiphy, false);
147}
148
136static int __iwm_up(struct iwm_priv *iwm); 149static int __iwm_up(struct iwm_priv *iwm);
137static int __iwm_down(struct iwm_priv *iwm); 150static int __iwm_down(struct iwm_priv *iwm);
138 151
@@ -225,6 +238,7 @@ int iwm_priv_init(struct iwm_priv *iwm)
225 iwm->scan_id = 1; 238 iwm->scan_id = 1;
226 INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request); 239 INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request);
227 INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work); 240 INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work);
241 INIT_DELAYED_WORK(&iwm->ct_kill_delay, iwm_ct_kill_work);
228 INIT_WORK(&iwm->reset_worker, iwm_reset_worker); 242 INIT_WORK(&iwm->reset_worker, iwm_reset_worker);
229 INIT_LIST_HEAD(&iwm->bss_list); 243 INIT_LIST_HEAD(&iwm->bss_list);
230 244
diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c
index 35ec006c2d2..4f8dbdd7b91 100644
--- a/drivers/net/wireless/iwmc3200wifi/netdev.c
+++ b/drivers/net/wireless/iwmc3200wifi/netdev.c
@@ -152,6 +152,7 @@ void iwm_if_free(struct iwm_priv *iwm)
152 if (!iwm_to_ndev(iwm)) 152 if (!iwm_to_ndev(iwm))
153 return; 153 return;
154 154
155 cancel_delayed_work_sync(&iwm->ct_kill_delay);
155 free_netdev(iwm_to_ndev(iwm)); 156 free_netdev(iwm_to_ndev(iwm));
156 iwm_priv_deinit(iwm); 157 iwm_priv_deinit(iwm);
157 kfree(iwm->umac_profile); 158 kfree(iwm->umac_profile);
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index 40dbcbc1659..14a2a0b3d61 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -1078,6 +1078,7 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
1078 return 0; 1078 return 0;
1079} 1079}
1080 1080
1081#define CT_KILL_DELAY (30 * HZ)
1081static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, 1082static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf,
1082 unsigned long buf_size, struct iwm_wifi_cmd *cmd) 1083 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
1083{ 1084{
@@ -1090,7 +1091,20 @@ static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf,
1090 flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF", 1091 flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF",
1091 flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF"); 1092 flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF");
1092 1093
1093 wiphy_rfkill_set_hw_state(wiphy, flags & IWM_CARD_STATE_HW_DISABLED); 1094 if (flags & IWM_CARD_STATE_CTKILL_DISABLED) {
1095 /*
1096 * We got a CTKILL event: We bring the interface down in
1097 * oder to cool the device down, and try to bring it up
1098 * 30 seconds later. If it's still too hot, we'll go through
1099 * this code path again.
1100 */
1101 cancel_delayed_work_sync(&iwm->ct_kill_delay);
1102 schedule_delayed_work(&iwm->ct_kill_delay, CT_KILL_DELAY);
1103 }
1104
1105 wiphy_rfkill_set_hw_state(wiphy, flags &
1106 (IWM_CARD_STATE_HW_DISABLED |
1107 IWM_CARD_STATE_CTKILL_DISABLED));
1094 1108
1095 return 0; 1109 return 0;
1096} 1110}