aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl3945-base.c
diff options
context:
space:
mode:
authorAdel Gadllah <adel.gadllah@gmail.com>2008-07-01 11:49:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-07-08 10:21:35 -0400
commit80fcc9e28cf3a209fbfb39a7bbddc313c59c7424 (patch)
treefe77fdd591652db82a87bff12d4b1528a1ecdfe4 /drivers/net/wireless/iwlwifi/iwl3945-base.c
parentebd74487d4b7a48ab8513ecfe3d321346d7c602e (diff)
iwlwifi: remove input device and fix rfkill state
This patch fixes the iwlwifi rfkill. It removes the input device from iwl3945, adds support for RFKILL_STATE_HARD_BLOCKED and calls rfkill_force_state() to update the state rather than accessing it directly. The calls to iwl|iwl3945_rfkill_set_hw_state() had to be moved because rfkill_force_state() cannot be called from an atomic context. Tested on iwl3945 and seems to work fine. Cc: Randy Dunlap <randy.dunlap@oracle.com> Cc: Ivo van Doorn <ivdoorn@gmail.com> Cc: Fabien Crespel <fcrespel@gmail.com> Cc: Zhu Yi <yi.zhu@intel.com> Cc: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c117
1 files changed, 50 insertions, 67 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index baa1abd5a14d..1a7d18fea89d 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -537,10 +537,20 @@ static inline int iwl3945_is_init(struct iwl3945_priv *priv)
537 return test_bit(STATUS_INIT, &priv->status); 537 return test_bit(STATUS_INIT, &priv->status);
538} 538}
539 539
540static inline int iwl3945_is_rfkill_sw(struct iwl3945_priv *priv)
541{
542 return test_bit(STATUS_RF_KILL_SW, &priv->status);
543}
544
545static inline int iwl3945_is_rfkill_hw(struct iwl3945_priv *priv)
546{
547 return test_bit(STATUS_RF_KILL_HW, &priv->status);
548}
549
540static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv) 550static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv)
541{ 551{
542 return test_bit(STATUS_RF_KILL_HW, &priv->status) || 552 return iwl3945_is_rfkill_hw(priv) ||
543 test_bit(STATUS_RF_KILL_SW, &priv->status); 553 iwl3945_is_rfkill_sw(priv);
544} 554}
545 555
546static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) 556static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv)
@@ -6013,12 +6023,11 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
6013 else { 6023 else {
6014 set_bit(STATUS_RF_KILL_HW, &priv->status); 6024 set_bit(STATUS_RF_KILL_HW, &priv->status);
6015 if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { 6025 if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
6016 iwl3945_rfkill_set_hw_state(priv);
6017 IWL_WARNING("Radio disabled by HW RF Kill switch\n"); 6026 IWL_WARNING("Radio disabled by HW RF Kill switch\n");
6018 return -ENODEV; 6027 return -ENODEV;
6019 } 6028 }
6020 } 6029 }
6021 iwl3945_rfkill_set_hw_state(priv); 6030
6022 iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); 6031 iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
6023 6032
6024 rc = iwl3945_hw_nic_init(priv); 6033 rc = iwl3945_hw_nic_init(priv);
@@ -6143,8 +6152,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
6143 "wireless networking to work.\n"); 6152 "wireless networking to work.\n");
6144 } 6153 }
6145 6154
6146 iwl3945_rfkill_set_hw_state(priv);
6147 mutex_unlock(&priv->mutex); 6155 mutex_unlock(&priv->mutex);
6156 iwl3945_rfkill_set_hw_state(priv);
6148} 6157}
6149 6158
6150static void iwl3945_bg_set_monitor(struct work_struct *work) 6159static void iwl3945_bg_set_monitor(struct work_struct *work)
@@ -6398,6 +6407,7 @@ static void iwl3945_bg_up(struct work_struct *data)
6398 mutex_lock(&priv->mutex); 6407 mutex_lock(&priv->mutex);
6399 __iwl3945_up(priv); 6408 __iwl3945_up(priv);
6400 mutex_unlock(&priv->mutex); 6409 mutex_unlock(&priv->mutex);
6410 iwl3945_rfkill_set_hw_state(priv);
6401} 6411}
6402 6412
6403static void iwl3945_bg_restart(struct work_struct *data) 6413static void iwl3945_bg_restart(struct work_struct *data)
@@ -6618,6 +6628,8 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
6618 6628
6619 mutex_unlock(&priv->mutex); 6629 mutex_unlock(&priv->mutex);
6620 6630
6631 iwl3945_rfkill_set_hw_state(priv);
6632
6621 if (ret) 6633 if (ret)
6622 goto out_release_irq; 6634 goto out_release_irq;
6623 6635
@@ -8276,14 +8288,14 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)
8276#endif /* CONFIG_PM */ 8288#endif /* CONFIG_PM */
8277 8289
8278/*************** RFKILL FUNCTIONS **********/ 8290/*************** RFKILL FUNCTIONS **********/
8279#ifdef CONFIG_IWLWIFI_RFKILL 8291#ifdef CONFIG_IWL3945_RFKILL
8280/* software rf-kill from user */ 8292/* software rf-kill from user */
8281static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) 8293static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
8282{ 8294{
8283 struct iwl3945_priv *priv = data; 8295 struct iwl3945_priv *priv = data;
8284 int err = 0; 8296 int err = 0;
8285 8297
8286 if (!priv->rfkill_mngr.rfkill) 8298 if (!priv->rfkill)
8287 return 0; 8299 return 0;
8288 8300
8289 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 8301 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -8294,20 +8306,20 @@ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
8294 8306
8295 switch (state) { 8307 switch (state) {
8296 case RFKILL_STATE_UNBLOCKED: 8308 case RFKILL_STATE_UNBLOCKED:
8297 iwl3945_radio_kill_sw(priv, 0); 8309 if (iwl3945_is_rfkill_hw(priv)) {
8298 /* if HW rf-kill is set dont allow ON state */
8299 if (iwl3945_is_rfkill(priv))
8300 err = -EBUSY; 8310 err = -EBUSY;
8311 goto out_unlock;
8312 }
8313 iwl3945_radio_kill_sw(priv, 0);
8301 break; 8314 break;
8302 case RFKILL_STATE_SOFT_BLOCKED: 8315 case RFKILL_STATE_SOFT_BLOCKED:
8303 iwl3945_radio_kill_sw(priv, 1); 8316 iwl3945_radio_kill_sw(priv, 1);
8304 if (!iwl3945_is_rfkill(priv))
8305 err = -EBUSY;
8306 break; 8317 break;
8307 default: 8318 default:
8308 IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); 8319 IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
8309 break; 8320 break;
8310 } 8321 }
8322out_unlock:
8311 mutex_unlock(&priv->mutex); 8323 mutex_unlock(&priv->mutex);
8312 8324
8313 return err; 8325 return err;
@@ -8321,64 +8333,35 @@ int iwl3945_rfkill_init(struct iwl3945_priv *priv)
8321 BUG_ON(device == NULL); 8333 BUG_ON(device == NULL);
8322 8334
8323 IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); 8335 IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
8324 priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); 8336 priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
8325 if (!priv->rfkill_mngr.rfkill) { 8337 if (!priv->rfkill) {
8326 IWL_ERROR("Unable to allocate rfkill device.\n"); 8338 IWL_ERROR("Unable to allocate rfkill device.\n");
8327 ret = -ENOMEM; 8339 ret = -ENOMEM;
8328 goto error; 8340 goto error;
8329 } 8341 }
8330 8342
8331 priv->rfkill_mngr.rfkill->name = priv->cfg->name; 8343 priv->rfkill->name = priv->cfg->name;
8332 priv->rfkill_mngr.rfkill->data = priv; 8344 priv->rfkill->data = priv;
8333 priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; 8345 priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
8334 priv->rfkill_mngr.rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; 8346 priv->rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill;
8335 priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; 8347 priv->rfkill->user_claim_unsupported = 1;
8336
8337 priv->rfkill_mngr.rfkill->dev.class->suspend = NULL;
8338 priv->rfkill_mngr.rfkill->dev.class->resume = NULL;
8339 8348
8340 priv->rfkill_mngr.input_dev = input_allocate_device(); 8349 priv->rfkill->dev.class->suspend = NULL;
8341 if (!priv->rfkill_mngr.input_dev) { 8350 priv->rfkill->dev.class->resume = NULL;
8342 IWL_ERROR("Unable to allocate rfkill input device.\n");
8343 ret = -ENOMEM;
8344 goto freed_rfkill;
8345 }
8346 8351
8347 priv->rfkill_mngr.input_dev->name = priv->cfg->name; 8352 ret = rfkill_register(priv->rfkill);
8348 priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy);
8349 priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST;
8350 priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor;
8351 priv->rfkill_mngr.input_dev->dev.parent = device;
8352 priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY);
8353 set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit);
8354
8355 ret = rfkill_register(priv->rfkill_mngr.rfkill);
8356 if (ret) { 8353 if (ret) {
8357 IWL_ERROR("Unable to register rfkill: %d\n", ret); 8354 IWL_ERROR("Unable to register rfkill: %d\n", ret);
8358 goto free_input_dev; 8355 goto freed_rfkill;
8359 }
8360
8361 ret = input_register_device(priv->rfkill_mngr.input_dev);
8362 if (ret) {
8363 IWL_ERROR("Unable to register rfkill input device: %d\n", ret);
8364 goto unregister_rfkill;
8365 } 8356 }
8366 8357
8367 IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); 8358 IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
8368 return ret; 8359 return ret;
8369 8360
8370unregister_rfkill:
8371 rfkill_unregister(priv->rfkill_mngr.rfkill);
8372 priv->rfkill_mngr.rfkill = NULL;
8373
8374free_input_dev:
8375 input_free_device(priv->rfkill_mngr.input_dev);
8376 priv->rfkill_mngr.input_dev = NULL;
8377
8378freed_rfkill: 8361freed_rfkill:
8379 if (priv->rfkill_mngr.rfkill != NULL) 8362 if (priv->rfkill != NULL)
8380 rfkill_free(priv->rfkill_mngr.rfkill); 8363 rfkill_free(priv->rfkill);
8381 priv->rfkill_mngr.rfkill = NULL; 8364 priv->rfkill = NULL;
8382 8365
8383error: 8366error:
8384 IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); 8367 IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
@@ -8387,28 +8370,28 @@ error:
8387 8370
8388void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) 8371void iwl3945_rfkill_unregister(struct iwl3945_priv *priv)
8389{ 8372{
8373 if (priv->rfkill)
8374 rfkill_unregister(priv->rfkill);
8390 8375
8391 if (priv->rfkill_mngr.input_dev) 8376 priv->rfkill = NULL;
8392 input_unregister_device(priv->rfkill_mngr.input_dev);
8393
8394 if (priv->rfkill_mngr.rfkill)
8395 rfkill_unregister(priv->rfkill_mngr.rfkill);
8396
8397 priv->rfkill_mngr.input_dev = NULL;
8398 priv->rfkill_mngr.rfkill = NULL;
8399} 8377}
8400 8378
8401/* set rf-kill to the right state. */ 8379/* set rf-kill to the right state. */
8402void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) 8380void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv)
8403{ 8381{
8404 8382
8405 if (!priv->rfkill_mngr.rfkill) 8383 if (!priv->rfkill)
8384 return;
8385
8386 if (iwl3945_is_rfkill_hw(priv)) {
8387 rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
8406 return; 8388 return;
8389 }
8407 8390
8408 if (!iwl3945_is_rfkill(priv)) 8391 if (!iwl3945_is_rfkill_sw(priv))
8409 priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; 8392 rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
8410 else 8393 else
8411 priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; 8394 rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
8412} 8395}
8413#endif 8396#endif
8414 8397