aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn.c
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2009-01-19 07:10:07 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:00:50 -0500
commit6cd0b1cb872b3bf9fc5de4536404206ab74bafdd (patch)
tree8ab5376e3f5750b053465bb18a8417608e2e31bc /drivers/net/wireless/iwlwifi/iwl-agn.c
parentc7e035a95d68819491b5250c6854f144c941e305 (diff)
iwlagn: fix hw-rfkill while the interface is down
Currently iwlagn 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 iwl_pci_probe instead of iwl_up and enable interrups while the interface is down in order to get notified about killswitch state changes. The firmware loading is still done in iwl_up. Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> Acked-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c110
1 files changed, 56 insertions, 54 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index b18596fed903..be14cd942a53 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1399,13 +1399,16 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
1399 hw_rf_kill ? "disable radio" : "enable radio"); 1399 hw_rf_kill ? "disable radio" : "enable radio");
1400 1400
1401 /* driver only loads ucode once setting the interface up. 1401 /* driver only loads ucode once setting the interface up.
1402 * the driver as well won't allow loading if RFKILL is set 1402 * the driver allows loading the ucode even if the radio
1403 * therefore no need to restart the driver from this handler 1403 * is killed. Hence update the killswitch state here. The
1404 * rfkill handler will care about restarting if needed.
1404 */ 1405 */
1405 if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) { 1406 if (!test_bit(STATUS_ALIVE, &priv->status)) {
1406 clear_bit(STATUS_RF_KILL_HW, &priv->status); 1407 if (hw_rf_kill)
1407 if (priv->is_open && !iwl_is_rfkill(priv)) 1408 set_bit(STATUS_RF_KILL_HW, &priv->status);
1408 queue_work(priv->workqueue, &priv->up); 1409 else
1410 clear_bit(STATUS_RF_KILL_HW, &priv->status);
1411 queue_work(priv->workqueue, &priv->rf_kill);
1409 } 1412 }
1410 1413
1411 handled |= CSR_INT_BIT_RF_KILL; 1414 handled |= CSR_INT_BIT_RF_KILL;
@@ -2158,7 +2161,8 @@ static void iwl_bg_rf_kill(struct work_struct *work)
2158 IWL_DEBUG(IWL_DL_RF_KILL, 2161 IWL_DEBUG(IWL_DL_RF_KILL,
2159 "HW and/or SW RF Kill no longer active, restarting " 2162 "HW and/or SW RF Kill no longer active, restarting "
2160 "device\n"); 2163 "device\n");
2161 if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) 2164 if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
2165 test_bit(STATUS_ALIVE, &priv->status))
2162 queue_work(priv->workqueue, &priv->restart); 2166 queue_work(priv->workqueue, &priv->restart);
2163 } else { 2167 } else {
2164 /* make sure mac80211 stop sending Tx frame */ 2168 /* make sure mac80211 stop sending Tx frame */
@@ -2355,31 +2359,9 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
2355{ 2359{
2356 struct iwl_priv *priv = hw->priv; 2360 struct iwl_priv *priv = hw->priv;
2357 int ret; 2361 int ret;
2358 u16 pci_cmd;
2359 2362
2360 IWL_DEBUG_MAC80211("enter\n"); 2363 IWL_DEBUG_MAC80211("enter\n");
2361 2364
2362 if (pci_enable_device(priv->pci_dev)) {
2363 IWL_ERR(priv, "Fail to pci_enable_device\n");
2364 return -ENODEV;
2365 }
2366 pci_restore_state(priv->pci_dev);
2367 pci_enable_msi(priv->pci_dev);
2368
2369 /* enable interrupts if needed: hw bug w/a */
2370 pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
2371 if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
2372 pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
2373 pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
2374 }
2375
2376 ret = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED,
2377 DRV_NAME, priv);
2378 if (ret) {
2379 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
2380 goto out_disable_msi;
2381 }
2382
2383 /* we should be verifying the device is ready to be opened */ 2365 /* we should be verifying the device is ready to be opened */
2384 mutex_lock(&priv->mutex); 2366 mutex_lock(&priv->mutex);
2385 2367
@@ -2392,7 +2374,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
2392 if (ret) { 2374 if (ret) {
2393 IWL_ERR(priv, "Could not read microcode: %d\n", ret); 2375 IWL_ERR(priv, "Could not read microcode: %d\n", ret);
2394 mutex_unlock(&priv->mutex); 2376 mutex_unlock(&priv->mutex);
2395 goto out_release_irq; 2377 return ret;
2396 } 2378 }
2397 } 2379 }
2398 2380
@@ -2403,7 +2385,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
2403 iwl_rfkill_set_hw_state(priv); 2385 iwl_rfkill_set_hw_state(priv);
2404 2386
2405 if (ret) 2387 if (ret)
2406 goto out_release_irq; 2388 return ret;
2407 2389
2408 if (iwl_is_rfkill(priv)) 2390 if (iwl_is_rfkill(priv))
2409 goto out; 2391 goto out;
@@ -2422,8 +2404,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
2422 if (!test_bit(STATUS_READY, &priv->status)) { 2404 if (!test_bit(STATUS_READY, &priv->status)) {
2423 IWL_ERR(priv, "START_ALIVE timeout after %dms.\n", 2405 IWL_ERR(priv, "START_ALIVE timeout after %dms.\n",
2424 jiffies_to_msecs(UCODE_READY_TIMEOUT)); 2406 jiffies_to_msecs(UCODE_READY_TIMEOUT));
2425 ret = -ETIMEDOUT; 2407 return -ETIMEDOUT;
2426 goto out_release_irq;
2427 } 2408 }
2428 } 2409 }
2429 2410
@@ -2431,15 +2412,6 @@ out:
2431 priv->is_open = 1; 2412 priv->is_open = 1;
2432 IWL_DEBUG_MAC80211("leave\n"); 2413 IWL_DEBUG_MAC80211("leave\n");
2433 return 0; 2414 return 0;
2434
2435out_release_irq:
2436 free_irq(priv->pci_dev->irq, priv);
2437out_disable_msi:
2438 pci_disable_msi(priv->pci_dev);
2439 pci_disable_device(priv->pci_dev);
2440 priv->is_open = 0;
2441 IWL_DEBUG_MAC80211("leave - failed\n");
2442 return ret;
2443} 2415}
2444 2416
2445static void iwl_mac_stop(struct ieee80211_hw *hw) 2417static void iwl_mac_stop(struct ieee80211_hw *hw)
@@ -2467,10 +2439,10 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
2467 iwl_down(priv); 2439 iwl_down(priv);
2468 2440
2469 flush_workqueue(priv->workqueue); 2441 flush_workqueue(priv->workqueue);
2470 free_irq(priv->pci_dev->irq, priv); 2442
2471 pci_disable_msi(priv->pci_dev); 2443 /* enable interrupts again in order to receive rfkill changes */
2472 pci_save_state(priv->pci_dev); 2444 iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
2473 pci_disable_device(priv->pci_dev); 2445 iwl_enable_interrupts(priv);
2474 2446
2475 IWL_DEBUG_MAC80211("leave\n"); 2447 IWL_DEBUG_MAC80211("leave\n");
2476} 2448}
@@ -3729,6 +3701,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3729 struct ieee80211_hw *hw; 3701 struct ieee80211_hw *hw;
3730 struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); 3702 struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
3731 unsigned long flags; 3703 unsigned long flags;
3704 u16 pci_cmd;
3732 3705
3733 /************************ 3706 /************************
3734 * 1. Allocating HW data 3707 * 1. Allocating HW data
@@ -3872,26 +3845,36 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3872 iwl_disable_interrupts(priv); 3845 iwl_disable_interrupts(priv);
3873 spin_unlock_irqrestore(&priv->lock, flags); 3846 spin_unlock_irqrestore(&priv->lock, flags);
3874 3847
3848 pci_enable_msi(priv->pci_dev);
3849
3850 err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED,
3851 DRV_NAME, priv);
3852 if (err) {
3853 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
3854 goto out_disable_msi;
3855 }
3875 err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group); 3856 err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
3876 if (err) { 3857 if (err) {
3877 IWL_ERR(priv, "failed to create sysfs device attributes\n"); 3858 IWL_ERR(priv, "failed to create sysfs device attributes\n");
3878 goto out_uninit_drv; 3859 goto out_uninit_drv;
3879 } 3860 }
3880 3861
3881
3882 iwl_setup_deferred_work(priv); 3862 iwl_setup_deferred_work(priv);
3883 iwl_setup_rx_handlers(priv); 3863 iwl_setup_rx_handlers(priv);
3884 3864
3885 /********************
3886 * 9. Conclude
3887 ********************/
3888 pci_save_state(pdev);
3889 pci_disable_device(pdev);
3890
3891 /********************************** 3865 /**********************************
3892 * 10. Setup and register mac80211 3866 * 9. Setup and register mac80211
3893 **********************************/ 3867 **********************************/
3894 3868
3869 /* enable interrupts if needed: hw bug w/a */
3870 pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
3871 if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
3872 pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
3873 pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
3874 }
3875
3876 iwl_enable_interrupts(priv);
3877
3895 err = iwl_setup_mac(priv); 3878 err = iwl_setup_mac(priv);
3896 if (err) 3879 if (err)
3897 goto out_remove_sysfs; 3880 goto out_remove_sysfs;
@@ -3900,15 +3883,27 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3900 if (err) 3883 if (err)
3901 IWL_ERR(priv, "failed to create debugfs files\n"); 3884 IWL_ERR(priv, "failed to create debugfs files\n");
3902 3885
3886 /* If platform's RF_KILL switch is NOT set to KILL */
3887 if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
3888 clear_bit(STATUS_RF_KILL_HW, &priv->status);
3889 else
3890 set_bit(STATUS_RF_KILL_HW, &priv->status);
3891
3903 err = iwl_rfkill_init(priv); 3892 err = iwl_rfkill_init(priv);
3904 if (err) 3893 if (err)
3905 IWL_ERR(priv, "Unable to initialize RFKILL system. " 3894 IWL_ERR(priv, "Unable to initialize RFKILL system. "
3906 "Ignoring error: %d\n", err); 3895 "Ignoring error: %d\n", err);
3896 else
3897 iwl_rfkill_set_hw_state(priv);
3898
3907 iwl_power_initialize(priv); 3899 iwl_power_initialize(priv);
3908 return 0; 3900 return 0;
3909 3901
3910 out_remove_sysfs: 3902 out_remove_sysfs:
3911 sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); 3903 sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
3904 out_disable_msi:
3905 pci_disable_msi(priv->pci_dev);
3906 pci_disable_device(priv->pci_dev);
3912 out_uninit_drv: 3907 out_uninit_drv:
3913 iwl_uninit_drv(priv); 3908 iwl_uninit_drv(priv);
3914 out_free_eeprom: 3909 out_free_eeprom:
@@ -3980,6 +3975,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
3980 destroy_workqueue(priv->workqueue); 3975 destroy_workqueue(priv->workqueue);
3981 priv->workqueue = NULL; 3976 priv->workqueue = NULL;
3982 3977
3978 free_irq(priv->pci_dev->irq, priv);
3979 pci_disable_msi(priv->pci_dev);
3983 pci_iounmap(pdev, priv->hw_base); 3980 pci_iounmap(pdev, priv->hw_base);
3984 pci_release_regions(pdev); 3981 pci_release_regions(pdev);
3985 pci_disable_device(pdev); 3982 pci_disable_device(pdev);
@@ -4005,6 +4002,8 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
4005 priv->is_open = 1; 4002 priv->is_open = 1;
4006 } 4003 }
4007 4004
4005 pci_save_state(pdev);
4006 pci_disable_device(pdev);
4008 pci_set_power_state(pdev, PCI_D3hot); 4007 pci_set_power_state(pdev, PCI_D3hot);
4009 4008
4010 return 0; 4009 return 0;
@@ -4015,6 +4014,9 @@ static int iwl_pci_resume(struct pci_dev *pdev)
4015 struct iwl_priv *priv = pci_get_drvdata(pdev); 4014 struct iwl_priv *priv = pci_get_drvdata(pdev);
4016 4015
4017 pci_set_power_state(pdev, PCI_D0); 4016 pci_set_power_state(pdev, PCI_D0);
4017 pci_enable_device(pdev);
4018 pci_restore_state(pdev);
4019 iwl_enable_interrupts(priv);
4018 4020
4019 if (priv->is_open) 4021 if (priv->is_open)
4020 iwl_mac_start(priv->hw); 4022 iwl_mac_start(priv->hw);