aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-core.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-06-13 03:44:55 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-14 12:18:11 -0400
commit14a08a7fcf72a8d69cdee225cc76c50b229faa20 (patch)
treefed4f75ab3551b205184a7cbecf6b7f532dd3c08 /drivers/net/wireless/iwlwifi/iwl-core.c
parent14b3d3387c95cc78f3d740ea53577d9ff41415e3 (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.c87
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}
1321EXPORT_SYMBOL(iwl_rf_kill_ct_config); 1321EXPORT_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 */
1333static 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
1345void 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}
1372EXPORT_SYMBOL(iwl_radio_kill_sw_disable_radio);
1373
1374int 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}
1408EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio);