diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 183 |
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 | ||
6349 | static int __iwl3945_up(struct iwl3945_priv *priv) | 6331 | static 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 | |||
6909 | static int iwl3945_mac_start(struct ieee80211_hw *hw) | 6885 | static 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 | |||
6945 | out_release_irq: | ||
6946 | free_irq(priv->pci_dev->irq, priv); | ||
6947 | out_disable_msi: | ||
6948 | pci_disable_msi(priv->pci_dev); | ||
6949 | return ret; | ||
6926 | } | 6950 | } |
6927 | 6951 | ||
6928 | static void iwl3945_mac_stop(struct ieee80211_hw *hw) | 6952 | static 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); |