diff options
author | Adel Gadllah <adel.gadllah@gmail.com> | 2008-07-01 11:49:50 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-07-08 10:21:35 -0400 |
commit | 80fcc9e28cf3a209fbfb39a7bbddc313c59c7424 (patch) | |
tree | fe77fdd591652db82a87bff12d4b1528a1ecdfe4 /drivers/net/wireless/iwlwifi/iwl3945-base.c | |
parent | ebd74487d4b7a48ab8513ecfe3d321346d7c602e (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.c | 117 |
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 | ||
540 | static inline int iwl3945_is_rfkill_sw(struct iwl3945_priv *priv) | ||
541 | { | ||
542 | return test_bit(STATUS_RF_KILL_SW, &priv->status); | ||
543 | } | ||
544 | |||
545 | static inline int iwl3945_is_rfkill_hw(struct iwl3945_priv *priv) | ||
546 | { | ||
547 | return test_bit(STATUS_RF_KILL_HW, &priv->status); | ||
548 | } | ||
549 | |||
540 | static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv) | 550 | static 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 | ||
546 | static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) | 556 | static 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 | ||
6150 | static void iwl3945_bg_set_monitor(struct work_struct *work) | 6159 | static 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 | ||
6403 | static void iwl3945_bg_restart(struct work_struct *data) | 6413 | static 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 */ |
8281 | static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | 8293 | static 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 | } |
8322 | out_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 | ||
8370 | unregister_rfkill: | ||
8371 | rfkill_unregister(priv->rfkill_mngr.rfkill); | ||
8372 | priv->rfkill_mngr.rfkill = NULL; | ||
8373 | |||
8374 | free_input_dev: | ||
8375 | input_free_device(priv->rfkill_mngr.input_dev); | ||
8376 | priv->rfkill_mngr.input_dev = NULL; | ||
8377 | |||
8378 | freed_rfkill: | 8361 | freed_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 | ||
8383 | error: | 8366 | error: |
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 | ||
8388 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) | 8371 | void 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. */ |
8402 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) | 8380 | void 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 | ||