aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2009-01-15 03:38:44 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:00:28 -0500
commit2663516d8fb896430bf42dce41b3e2f141d63bd5 (patch)
treed53989bd9ca5b2b722f5a804420c7ec0175b959b /drivers
parentc95741deef31d14c3a3d58397f9a3d2126d452e5 (diff)
iwl3945: report killswitch changes even if the interface is down
Currently iwl3945 is not able to report hw-killswitch events while the interface is down. This has implications on user space tools (like NetworkManager) relying on rfkill notifications to bring the interface up once the wireless gets enabled through a hw killswitch. Thus, enable the device already in iwl3945_pci_probe instead of iwl3945_up and poll the CSR_GP_CNTRL register to update the killswitch state every two seconds. The polling is only needed on 3945 hardware as this adapter does not use interrupts to signal rfkill changes to the driver (in case no firmware is loaded). The firmware loading is still done in iwl3945_up. Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> Acked-by: Samuel Ortiz <samuel.ortiz@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c88
2 files changed, 57 insertions, 32 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index fd34ba81a0df..4d437cf50c8e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1041,6 +1041,7 @@ struct iwl_priv {
1041 1041
1042 /*For 3945 only*/ 1042 /*For 3945 only*/
1043 struct delayed_work thermal_periodic; 1043 struct delayed_work thermal_periodic;
1044 struct delayed_work rfkill_poll;
1044 1045
1045 /* TX Power */ 1046 /* TX Power */
1046 s8 tx_power_user_lmt; 1047 s8 tx_power_user_lmt;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 1b04284c4ca8..050d532475ca 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -5479,7 +5479,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
5479 IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL, 5479 IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
5480 "HW and/or SW RF Kill no longer active, restarting " 5480 "HW and/or SW RF Kill no longer active, restarting "
5481 "device\n"); 5481 "device\n");
5482 if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) 5482 if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
5483 test_bit(STATUS_ALIVE, &priv->status))
5483 queue_work(priv->workqueue, &priv->restart); 5484 queue_work(priv->workqueue, &priv->restart);
5484 } else { 5485 } else {
5485 5486
@@ -5496,6 +5497,25 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
5496 iwl3945_rfkill_set_hw_state(priv); 5497 iwl3945_rfkill_set_hw_state(priv);
5497} 5498}
5498 5499
5500static void iwl3945_rfkill_poll(struct work_struct *data)
5501{
5502 struct iwl_priv *priv =
5503 container_of(data, struct iwl_priv, rfkill_poll.work);
5504 unsigned long status = priv->status;
5505
5506 if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
5507 clear_bit(STATUS_RF_KILL_HW, &priv->status);
5508 else
5509 set_bit(STATUS_RF_KILL_HW, &priv->status);
5510
5511 if (test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status))
5512 queue_work(priv->workqueue, &priv->rf_kill);
5513
5514 queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
5515 round_jiffies_relative(2 * HZ));
5516
5517}
5518
5499#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) 5519#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
5500 5520
5501static void iwl3945_bg_scan_check(struct work_struct *data) 5521static void iwl3945_bg_scan_check(struct work_struct *data)
@@ -5898,20 +5918,6 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
5898 5918
5899 IWL_DEBUG_MAC80211("enter\n"); 5919 IWL_DEBUG_MAC80211("enter\n");
5900 5920
5901 if (pci_enable_device(priv->pci_dev)) {
5902 IWL_ERR(priv, "Fail to pci_enable_device\n");
5903 return -ENODEV;
5904 }
5905 pci_restore_state(priv->pci_dev);
5906 pci_enable_msi(priv->pci_dev);
5907
5908 ret = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED,
5909 DRV_NAME, priv);
5910 if (ret) {
5911 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
5912 goto out_disable_msi;
5913 }
5914
5915 /* we should be verifying the device is ready to be opened */ 5921 /* we should be verifying the device is ready to be opened */
5916 mutex_lock(&priv->mutex); 5922 mutex_lock(&priv->mutex);
5917 5923
@@ -5957,15 +5963,15 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
5957 } 5963 }
5958 } 5964 }
5959 5965
5966 /* ucode is running and will send rfkill notifications,
5967 * no need to poll the killswitch state anymore */
5968 cancel_delayed_work(&priv->rfkill_poll);
5969
5960 priv->is_open = 1; 5970 priv->is_open = 1;
5961 IWL_DEBUG_MAC80211("leave\n"); 5971 IWL_DEBUG_MAC80211("leave\n");
5962 return 0; 5972 return 0;
5963 5973
5964out_release_irq: 5974out_release_irq:
5965 free_irq(priv->pci_dev->irq, priv);
5966out_disable_msi:
5967 pci_disable_msi(priv->pci_dev);
5968 pci_disable_device(priv->pci_dev);
5969 priv->is_open = 0; 5975 priv->is_open = 0;
5970 IWL_DEBUG_MAC80211("leave - failed\n"); 5976 IWL_DEBUG_MAC80211("leave - failed\n");
5971 return ret; 5977 return ret;
@@ -5996,10 +6002,10 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
5996 iwl3945_down(priv); 6002 iwl3945_down(priv);
5997 6003
5998 flush_workqueue(priv->workqueue); 6004 flush_workqueue(priv->workqueue);
5999 free_irq(priv->pci_dev->irq, priv); 6005
6000 pci_disable_msi(priv->pci_dev); 6006 /* start polling the killswitch state again */
6001 pci_save_state(priv->pci_dev); 6007 queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
6002 pci_disable_device(priv->pci_dev); 6008 round_jiffies_relative(2 * HZ));
6003 6009
6004 IWL_DEBUG_MAC80211("leave\n"); 6010 IWL_DEBUG_MAC80211("leave\n");
6005} 6011}
@@ -7207,6 +7213,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
7207 INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); 7213 INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
7208 INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); 7214 INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
7209 INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check); 7215 INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check);
7216 INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll);
7210 7217
7211 iwl3945_hw_setup_deferred_work(priv); 7218 iwl3945_hw_setup_deferred_work(priv);
7212 7219
@@ -7497,6 +7504,15 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
7497 iwl3945_disable_interrupts(priv); 7504 iwl3945_disable_interrupts(priv);
7498 spin_unlock_irqrestore(&priv->lock, flags); 7505 spin_unlock_irqrestore(&priv->lock, flags);
7499 7506
7507 pci_enable_msi(priv->pci_dev);
7508
7509 err = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED,
7510 DRV_NAME, priv);
7511 if (err) {
7512 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
7513 goto out_disable_msi;
7514 }
7515
7500 err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); 7516 err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
7501 if (err) { 7517 if (err) {
7502 IWL_ERR(priv, "failed to create sysfs device attributes\n"); 7518 IWL_ERR(priv, "failed to create sysfs device attributes\n");
@@ -7507,14 +7523,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
7507 iwl3945_setup_deferred_work(priv); 7523 iwl3945_setup_deferred_work(priv);
7508 iwl3945_setup_rx_handlers(priv); 7524 iwl3945_setup_rx_handlers(priv);
7509 7525
7510 /***********************
7511 * 9. Conclude
7512 * ********************/
7513 pci_save_state(pdev);
7514 pci_disable_device(pdev);
7515
7516 /********************************* 7526 /*********************************
7517 * 10. Setup and Register mac80211 7527 * 9. Setup and Register mac80211
7518 * *******************************/ 7528 * *******************************/
7519 7529
7520 err = ieee80211_register_hw(priv->hw); 7530 err = ieee80211_register_hw(priv->hw);
@@ -7531,6 +7541,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
7531 IWL_ERR(priv, "Unable to initialize RFKILL system. " 7541 IWL_ERR(priv, "Unable to initialize RFKILL system. "
7532 "Ignoring error: %d\n", err); 7542 "Ignoring error: %d\n", err);
7533 7543
7544 /* Start monitoring the killswitch */
7545 queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
7546 2 * HZ);
7547
7534 return 0; 7548 return 0;
7535 7549
7536 out_remove_sysfs: 7550 out_remove_sysfs:
@@ -7539,10 +7553,12 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
7539 iwl3945_free_geos(priv); 7553 iwl3945_free_geos(priv);
7540 7554
7541 out_release_irq: 7555 out_release_irq:
7556 free_irq(priv->pci_dev->irq, priv);
7542 destroy_workqueue(priv->workqueue); 7557 destroy_workqueue(priv->workqueue);
7543 priv->workqueue = NULL; 7558 priv->workqueue = NULL;
7544 iwl3945_unset_hw_params(priv); 7559 iwl3945_unset_hw_params(priv);
7545 7560 out_disable_msi:
7561 pci_disable_msi(priv->pci_dev);
7546 out_iounmap: 7562 out_iounmap:
7547 pci_iounmap(pdev, priv->hw_base); 7563 pci_iounmap(pdev, priv->hw_base);
7548 out_pci_release_regions: 7564 out_pci_release_regions:
@@ -7587,6 +7603,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
7587 sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); 7603 sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
7588 7604
7589 iwl3945_rfkill_unregister(priv); 7605 iwl3945_rfkill_unregister(priv);
7606 cancel_delayed_work(&priv->rfkill_poll);
7607
7590 iwl3945_dealloc_ucode_pci(priv); 7608 iwl3945_dealloc_ucode_pci(priv);
7591 7609
7592 if (priv->rxq.bd) 7610 if (priv->rxq.bd)
@@ -7605,6 +7623,9 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
7605 destroy_workqueue(priv->workqueue); 7623 destroy_workqueue(priv->workqueue);
7606 priv->workqueue = NULL; 7624 priv->workqueue = NULL;
7607 7625
7626 free_irq(pdev->irq, priv);
7627 pci_disable_msi(pdev);
7628
7608 pci_iounmap(pdev, priv->hw_base); 7629 pci_iounmap(pdev, priv->hw_base);
7609 pci_release_regions(pdev); 7630 pci_release_regions(pdev);
7610 pci_disable_device(pdev); 7631 pci_disable_device(pdev);
@@ -7630,7 +7651,8 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
7630 iwl3945_mac_stop(priv->hw); 7651 iwl3945_mac_stop(priv->hw);
7631 priv->is_open = 1; 7652 priv->is_open = 1;
7632 } 7653 }
7633 7654 pci_save_state(pdev);
7655 pci_disable_device(pdev);
7634 pci_set_power_state(pdev, PCI_D3hot); 7656 pci_set_power_state(pdev, PCI_D3hot);
7635 7657
7636 return 0; 7658 return 0;
@@ -7641,6 +7663,8 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)
7641 struct iwl_priv *priv = pci_get_drvdata(pdev); 7663 struct iwl_priv *priv = pci_get_drvdata(pdev);
7642 7664
7643 pci_set_power_state(pdev, PCI_D0); 7665 pci_set_power_state(pdev, PCI_D0);
7666 pci_enable_device(pdev);
7667 pci_restore_state(pdev);
7644 7668
7645 if (priv->is_open) 7669 if (priv->is_open)
7646 iwl3945_mac_start(priv->hw); 7670 iwl3945_mac_start(priv->hw);