aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl3945-base.c
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2008-01-14 20:46:18 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:09:57 -0500
commit5a66926aa9230810704fd5a127966215fd58881e (patch)
tree347aa0458a71130357afcd89bb17a264cf728302 /drivers/net/wireless/iwlwifi/iwl3945-base.c
parent3058f02137359efb412975cf94a9fa7c25413387 (diff)
iwlwifi: delay firmware loading from pci_probe to network interface open
This patch moves the firmware loading (read firmware from disk and load it into the device SRAM) from pci_probe time to the first network interface open time. There are two reasons for doing this: 1. To support kernel buildin iwlwifi drivers. Because kernel initializes network devices subsystem before hard disk and SATA subsystem, it is impossible to get the firmware image from hard disk in the PCI probe handler. Thus delaying the firmware loading into the network interface open time is the way to go. Note, we only read the firmware image from hard disk the first time the interface is open. After this is succeeded, we cache the firmware image into the host memory. This is a performance gain when user open and close the interface multiple times and is necessary for device suspend and resume. 2. For better power saving. When the iwlwifi modules are loaded (or buildin the kernel) but the wireless network interface is not being used, it is a good practice the wireless device consumes as less power as possible. Unloading the firmware from the wireless device and unregister the driver's interrupt handler in the network interface close handler provides users a way to achieve this. User space network configuration tools (i.e NetworkManager) can also contribute here when it detects a wired cable is connected and close the wireless interface automatically. This patch also includes the pci_save/restore_state() fixed by Ian Schram upon the first version. Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: Ian Schram <ischram@telenet.be> 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.c183
1 files changed, 107 insertions, 76 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 1830e13d5cfd..e0e9bbdf140f 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -6179,31 +6179,12 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
6179 } 6179 }
6180 6180
6181 iwl3945_init_geos(priv); 6181 iwl3945_init_geos(priv);
6182 iwl3945_reset_channel_flag(priv);
6182 6183
6183 if (iwl3945_is_rfkill(priv)) 6184 if (iwl3945_is_rfkill(priv))
6184 return; 6185 return;
6185 6186
6186 if (!priv->mac80211_registered) { 6187 ieee80211_start_queues(priv->hw);
6187 /* Unlock so any user space entry points can call back into
6188 * the driver without a deadlock... */
6189 mutex_unlock(&priv->mutex);
6190 iwl3945_rate_control_register(priv->hw);
6191 rc = ieee80211_register_hw(priv->hw);
6192 priv->hw->conf.beacon_int = 100;
6193 mutex_lock(&priv->mutex);
6194
6195 if (rc) {
6196 iwl3945_rate_control_unregister(priv->hw);
6197 IWL_ERROR("Failed to register network "
6198 "device (error %d)\n", rc);
6199 return;
6200 }
6201
6202 priv->mac80211_registered = 1;
6203
6204 iwl3945_reset_channel_flag(priv);
6205 } else
6206 ieee80211_start_queues(priv->hw);
6207 6188
6208 priv->active_rate = priv->rates_mask; 6189 priv->active_rate = priv->rates_mask;
6209 priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; 6190 priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
@@ -6236,6 +6217,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
6236 iwl3945_reg_txpower_periodic(priv); 6217 iwl3945_reg_txpower_periodic(priv);
6237 6218
6238 IWL_DEBUG_INFO("ALIVE processing complete.\n"); 6219 IWL_DEBUG_INFO("ALIVE processing complete.\n");
6220 wake_up_interruptible(&priv->wait_command_queue);
6239 6221
6240 if (priv->error_recovering) 6222 if (priv->error_recovering)
6241 iwl3945_error_recovery(priv); 6223 iwl3945_error_recovery(priv);
@@ -6348,7 +6330,6 @@ static void iwl3945_down(struct iwl3945_priv *priv)
6348 6330
6349static int __iwl3945_up(struct iwl3945_priv *priv) 6331static int __iwl3945_up(struct iwl3945_priv *priv)
6350{ 6332{
6351 DECLARE_MAC_BUF(mac);
6352 int rc, i; 6333 int rc, i;
6353 6334
6354 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { 6335 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
@@ -6392,7 +6373,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
6392 * This will be used to initialize the on-board processor's 6373 * This will be used to initialize the on-board processor's
6393 * data SRAM for a clean start when the runtime program first loads. */ 6374 * data SRAM for a clean start when the runtime program first loads. */
6394 memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr, 6375 memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
6395 priv->ucode_data.len); 6376 priv->ucode_data.len);
6396 6377
6397 for (i = 0; i < MAX_HW_RESTARTS; i++) { 6378 for (i = 0; i < MAX_HW_RESTARTS; i++) {
6398 6379
@@ -6411,13 +6392,6 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
6411 /* start card; "initialize" will load runtime ucode */ 6392 /* start card; "initialize" will load runtime ucode */
6412 iwl3945_nic_start(priv); 6393 iwl3945_nic_start(priv);
6413 6394
6414 /* MAC Address location in EEPROM is same for 3945/4965 */
6415 get_eeprom_mac(priv, priv->mac_addr);
6416 IWL_DEBUG_INFO("MAC address: %s\n",
6417 print_mac(mac, priv->mac_addr));
6418
6419 SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
6420
6421 IWL_DEBUG_INFO(DRV_NAME " is coming up\n"); 6395 IWL_DEBUG_INFO(DRV_NAME " is coming up\n");
6422 6396
6423 return 0; 6397 return 0;
@@ -6906,23 +6880,73 @@ static void iwl3945_bg_scan_completed(struct work_struct *work)
6906 * 6880 *
6907 *****************************************************************************/ 6881 *****************************************************************************/
6908 6882
6883#define UCODE_READY_TIMEOUT (2 * HZ)
6884
6909static int iwl3945_mac_start(struct ieee80211_hw *hw) 6885static int iwl3945_mac_start(struct ieee80211_hw *hw)
6910{ 6886{
6911 struct iwl3945_priv *priv = hw->priv; 6887 struct iwl3945_priv *priv = hw->priv;
6888 int ret;
6912 6889
6913 IWL_DEBUG_MAC80211("enter\n"); 6890 IWL_DEBUG_MAC80211("enter\n");
6914 6891
6892 if (pci_enable_device(priv->pci_dev)) {
6893 IWL_ERROR("Fail to pci_enable_device\n");
6894 return -ENODEV;
6895 }
6896 pci_restore_state(priv->pci_dev);
6897 pci_enable_msi(priv->pci_dev);
6898
6899 ret = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED,
6900 DRV_NAME, priv);
6901 if (ret) {
6902 IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq);
6903 goto out_disable_msi;
6904 }
6905
6915 /* we should be verifying the device is ready to be opened */ 6906 /* we should be verifying the device is ready to be opened */
6916 mutex_lock(&priv->mutex); 6907 mutex_lock(&priv->mutex);
6917 6908
6918 priv->is_open = 1; 6909 memset(&priv->staging_rxon, 0, sizeof(struct iwl3945_rxon_cmd));
6910 /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
6911 * ucode filename and max sizes are card-specific. */
6919 6912
6920 if (!iwl3945_is_rfkill(priv)) 6913 if (!priv->ucode_code.len) {
6921 ieee80211_start_queues(priv->hw); 6914 ret = iwl3945_read_ucode(priv);
6915 if (ret) {
6916 IWL_ERROR("Could not read microcode: %d\n", ret);
6917 mutex_unlock(&priv->mutex);
6918 goto out_release_irq;
6919 }
6920 }
6922 6921
6922 IWL_DEBUG_INFO("Start UP work.\n");
6923 __iwl3945_up(priv);
6924
6925 priv->is_open = 1;
6923 mutex_unlock(&priv->mutex); 6926 mutex_unlock(&priv->mutex);
6927
6928 /* Wait for START_ALIVE from ucode. Otherwise callbacks from
6929 * mac80211 will not be run successfully. */
6930 ret = wait_event_interruptible_timeout(priv->wait_command_queue,
6931 test_bit(STATUS_READY, &priv->status),
6932 UCODE_READY_TIMEOUT);
6933 if (!ret) {
6934 if (!test_bit(STATUS_READY, &priv->status)) {
6935 IWL_ERROR("Wait for START_ALIVE timeout after %dms.\n",
6936 jiffies_to_msecs(UCODE_READY_TIMEOUT));
6937 ret = -ETIMEDOUT;
6938 goto out_release_irq;
6939 }
6940 }
6941
6924 IWL_DEBUG_MAC80211("leave\n"); 6942 IWL_DEBUG_MAC80211("leave\n");
6925 return 0; 6943 return 0;
6944
6945out_release_irq:
6946 free_irq(priv->pci_dev->irq, priv);
6947out_disable_msi:
6948 pci_disable_msi(priv->pci_dev);
6949 return ret;
6926} 6950}
6927 6951
6928static void iwl3945_mac_stop(struct ieee80211_hw *hw) 6952static void iwl3945_mac_stop(struct ieee80211_hw *hw)
@@ -6931,23 +6955,25 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
6931 6955
6932 IWL_DEBUG_MAC80211("enter\n"); 6956 IWL_DEBUG_MAC80211("enter\n");
6933 6957
6934
6935 mutex_lock(&priv->mutex);
6936 /* stop mac, cancel any scan request and clear 6958 /* stop mac, cancel any scan request and clear
6937 * RXON_FILTER_ASSOC_MSK BIT 6959 * RXON_FILTER_ASSOC_MSK BIT
6938 */ 6960 */
6939 priv->is_open = 0; 6961 priv->is_open = 0;
6940 if (!iwl3945_is_ready_rf(priv)) { 6962
6941 IWL_DEBUG_MAC80211("leave - RF not ready\n"); 6963 if (iwl3945_is_ready_rf(priv)) {
6964 mutex_lock(&priv->mutex);
6965 iwl3945_scan_cancel_timeout(priv, 100);
6966 cancel_delayed_work(&priv->post_associate);
6942 mutex_unlock(&priv->mutex); 6967 mutex_unlock(&priv->mutex);
6943 return;
6944 } 6968 }
6945 6969
6946 iwl3945_scan_cancel_timeout(priv, 100); 6970 iwl3945_down(priv);
6947 cancel_delayed_work(&priv->post_associate); 6971
6948 priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; 6972 flush_workqueue(priv->workqueue);
6949 iwl3945_commit_rxon(priv); 6973 free_irq(priv->pci_dev->irq, priv);
6950 mutex_unlock(&priv->mutex); 6974 pci_disable_msi(priv->pci_dev);
6975 pci_save_state(priv->pci_dev);
6976 pci_disable_device(priv->pci_dev);
6951 6977
6952 IWL_DEBUG_MAC80211("leave\n"); 6978 IWL_DEBUG_MAC80211("leave\n");
6953} 6979}
@@ -7000,11 +7026,12 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
7000 memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); 7026 memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
7001 } 7027 }
7002 7028
7003 iwl3945_set_mode(priv, conf->type); 7029 if (iwl3945_is_ready(priv))
7030 iwl3945_set_mode(priv, conf->type);
7004 7031
7005 IWL_DEBUG_MAC80211("leave\n");
7006 mutex_unlock(&priv->mutex); 7032 mutex_unlock(&priv->mutex);
7007 7033
7034 IWL_DEBUG_MAC80211("leave\n");
7008 return 0; 7035 return 0;
7009} 7036}
7010 7037
@@ -7178,6 +7205,9 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
7178 return 0; 7205 return 0;
7179 } 7206 }
7180 7207
7208 if (!iwl3945_is_alive(priv))
7209 return -EAGAIN;
7210
7181 mutex_lock(&priv->mutex); 7211 mutex_lock(&priv->mutex);
7182 7212
7183 if (conf->bssid) 7213 if (conf->bssid)
@@ -8390,6 +8420,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
8390 struct iwl3945_priv *priv; 8420 struct iwl3945_priv *priv;
8391 struct ieee80211_hw *hw; 8421 struct ieee80211_hw *hw;
8392 int i; 8422 int i;
8423 DECLARE_MAC_BUF(mac);
8393 8424
8394 /* Disabling hardware scan means that mac80211 will perform scans 8425 /* Disabling hardware scan means that mac80211 will perform scans
8395 * "the hard way", rather than using device's scan. */ 8426 * "the hard way", rather than using device's scan. */
@@ -8542,7 +8573,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
8542 /* Device-specific setup */ 8573 /* Device-specific setup */
8543 if (iwl3945_hw_set_hw_setting(priv)) { 8574 if (iwl3945_hw_set_hw_setting(priv)) {
8544 IWL_ERROR("failed to set hw settings\n"); 8575 IWL_ERROR("failed to set hw settings\n");
8545 mutex_unlock(&priv->mutex);
8546 goto out_iounmap; 8576 goto out_iounmap;
8547 } 8577 }
8548 8578
@@ -8567,50 +8597,53 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
8567 8597
8568 iwl3945_disable_interrupts(priv); 8598 iwl3945_disable_interrupts(priv);
8569 8599
8570 pci_enable_msi(pdev);
8571
8572 err = request_irq(pdev->irq, iwl3945_isr, IRQF_SHARED, DRV_NAME, priv);
8573 if (err) {
8574 IWL_ERROR("Error allocating IRQ %d\n", pdev->irq);
8575 goto out_disable_msi;
8576 }
8577
8578 mutex_lock(&priv->mutex);
8579
8580 err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); 8600 err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
8581 if (err) { 8601 if (err) {
8582 IWL_ERROR("failed to create sysfs device attributes\n"); 8602 IWL_ERROR("failed to create sysfs device attributes\n");
8583 mutex_unlock(&priv->mutex);
8584 goto out_release_irq; 8603 goto out_release_irq;
8585 } 8604 }
8586 8605
8587 /* fetch ucode file from disk, alloc and copy to bus-master buffers ... 8606 /* nic init */
8588 * ucode filename and max sizes are card-specific. */ 8607 iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
8589 err = iwl3945_read_ucode(priv); 8608 CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
8609
8610 iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
8611 err = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
8612 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
8613 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
8614 if (err < 0) {
8615 IWL_DEBUG_INFO("Failed to init the card\n");
8616 goto out_remove_sysfs;
8617 }
8618 /* Read the EEPROM */
8619 err = iwl3945_eeprom_init(priv);
8590 if (err) { 8620 if (err) {
8591 IWL_ERROR("Could not read microcode: %d\n", err); 8621 IWL_ERROR("Unable to init EEPROM\n");
8592 mutex_unlock(&priv->mutex); 8622 goto out_remove_sysfs;
8593 goto out_pci_alloc;
8594 } 8623 }
8624 /* MAC Address location in EEPROM same for 3945/4965 */
8625 get_eeprom_mac(priv, priv->mac_addr);
8626 IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
8627 SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
8595 8628
8596 mutex_unlock(&priv->mutex); 8629 iwl3945_rate_control_register(priv->hw);
8597 8630 err = ieee80211_register_hw(priv->hw);
8598 IWL_DEBUG_INFO("Queueing UP work.\n"); 8631 if (err) {
8632 IWL_ERROR("Failed to register network device (error %d)\n", err);
8633 goto out_remove_sysfs;
8634 }
8599 8635
8600 queue_work(priv->workqueue, &priv->up); 8636 priv->hw->conf.beacon_int = 100;
8637 priv->mac80211_registered = 1;
8638 pci_save_state(pdev);
8639 pci_disable_device(pdev);
8601 8640
8602 return 0; 8641 return 0;
8603 8642
8604 out_pci_alloc: 8643 out_remove_sysfs:
8605 iwl3945_dealloc_ucode_pci(priv);
8606
8607 sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); 8644 sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
8608 8645
8609 out_release_irq: 8646 out_release_irq:
8610 free_irq(pdev->irq, priv);
8611
8612 out_disable_msi:
8613 pci_disable_msi(pdev);
8614 destroy_workqueue(priv->workqueue); 8647 destroy_workqueue(priv->workqueue);
8615 priv->workqueue = NULL; 8648 priv->workqueue = NULL;
8616 iwl3945_unset_hw_setting(priv); 8649 iwl3945_unset_hw_setting(priv);
@@ -8676,8 +8709,6 @@ static void iwl3945_pci_remove(struct pci_dev *pdev)
8676 destroy_workqueue(priv->workqueue); 8709 destroy_workqueue(priv->workqueue);
8677 priv->workqueue = NULL; 8710 priv->workqueue = NULL;
8678 8711
8679 free_irq(pdev->irq, priv);
8680 pci_disable_msi(pdev);
8681 pci_iounmap(pdev, priv->hw_base); 8712 pci_iounmap(pdev, priv->hw_base);
8682 pci_release_regions(pdev); 8713 pci_release_regions(pdev);
8683 pci_disable_device(pdev); 8714 pci_disable_device(pdev);