diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2008-06-13 03:44:55 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-06-14 12:18:11 -0400 |
commit | 14a08a7fcf72a8d69cdee225cc76c50b229faa20 (patch) | |
tree | fed4f75ab3551b205184a7cbecf6b7f532dd3c08 /drivers/net/wireless/iwlwifi/iwl-core.c | |
parent | 14b3d3387c95cc78f3d740ea53577d9ff41415e3 (diff) |
iwlwifi: unify SW rf-kill flow
This patch unifies SW rf-kill flow between 4965 and 5000. It enables SW
RF-kill for 5000. This patch also solves a bug in iwl4965_mac_config:
bad mutex locking balance.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-core.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index fa17cd9838cb..eb74a40a62eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -1319,3 +1319,90 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
1319 | cmd.critical_temperature_R); | 1319 | cmd.critical_temperature_R); |
1320 | } | 1320 | } |
1321 | EXPORT_SYMBOL(iwl_rf_kill_ct_config); | 1321 | EXPORT_SYMBOL(iwl_rf_kill_ct_config); |
1322 | |||
1323 | /* | ||
1324 | * CARD_STATE_CMD | ||
1325 | * | ||
1326 | * Use: Sets the device's internal card state to enable, disable, or halt | ||
1327 | * | ||
1328 | * When in the 'enable' state the card operates as normal. | ||
1329 | * When in the 'disable' state, the card enters into a low power mode. | ||
1330 | * When in the 'halt' state, the card is shut down and must be fully | ||
1331 | * restarted to come back on. | ||
1332 | */ | ||
1333 | static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) | ||
1334 | { | ||
1335 | struct iwl_host_cmd cmd = { | ||
1336 | .id = REPLY_CARD_STATE_CMD, | ||
1337 | .len = sizeof(u32), | ||
1338 | .data = &flags, | ||
1339 | .meta.flags = meta_flag, | ||
1340 | }; | ||
1341 | |||
1342 | return iwl_send_cmd(priv, &cmd); | ||
1343 | } | ||
1344 | |||
1345 | void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv) | ||
1346 | { | ||
1347 | unsigned long flags; | ||
1348 | |||
1349 | if (test_bit(STATUS_RF_KILL_SW, &priv->status)) | ||
1350 | return; | ||
1351 | |||
1352 | IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO OFF\n"); | ||
1353 | |||
1354 | iwl_scan_cancel(priv); | ||
1355 | /* FIXME: This is a workaround for AP */ | ||
1356 | if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { | ||
1357 | spin_lock_irqsave(&priv->lock, flags); | ||
1358 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | ||
1359 | CSR_UCODE_SW_BIT_RFKILL); | ||
1360 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1361 | /* call the host command only if no hw rf-kill set */ | ||
1362 | if (!test_bit(STATUS_RF_KILL_HW, &priv->status) && | ||
1363 | iwl_is_ready(priv)) | ||
1364 | iwl_send_card_state(priv, | ||
1365 | CARD_STATE_CMD_DISABLE, 0); | ||
1366 | set_bit(STATUS_RF_KILL_SW, &priv->status); | ||
1367 | /* make sure mac80211 stop sending Tx frame */ | ||
1368 | if (priv->mac80211_registered) | ||
1369 | ieee80211_stop_queues(priv->hw); | ||
1370 | } | ||
1371 | } | ||
1372 | EXPORT_SYMBOL(iwl_radio_kill_sw_disable_radio); | ||
1373 | |||
1374 | int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv) | ||
1375 | { | ||
1376 | unsigned long flags; | ||
1377 | |||
1378 | if (!test_bit(STATUS_RF_KILL_SW, &priv->status)) | ||
1379 | return 0; | ||
1380 | |||
1381 | IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO ON\n"); | ||
1382 | |||
1383 | spin_lock_irqsave(&priv->lock, flags); | ||
1384 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
1385 | |||
1386 | clear_bit(STATUS_RF_KILL_SW, &priv->status); | ||
1387 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1388 | |||
1389 | /* wake up ucode */ | ||
1390 | msleep(10); | ||
1391 | |||
1392 | spin_lock_irqsave(&priv->lock, flags); | ||
1393 | iwl_read32(priv, CSR_UCODE_DRV_GP1); | ||
1394 | if (!iwl_grab_nic_access(priv)) | ||
1395 | iwl_release_nic_access(priv); | ||
1396 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1397 | |||
1398 | if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { | ||
1399 | IWL_DEBUG_RF_KILL("Can not turn radio back on - " | ||
1400 | "disabled by HW switch\n"); | ||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | if (priv->is_open) | ||
1405 | queue_work(priv->workqueue, &priv->restart); | ||
1406 | return 1; | ||
1407 | } | ||
1408 | EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio); | ||