]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/iwlwifi/iwl3945-base.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-linus
[linux-2.6] / drivers / net / wireless / iwlwifi / iwl3945-base.c
index e0e9bbdf140fad17aef1d6fa1b5be55cec3abe1b..40b71bc2c4a4c3eea35c5896d4293e20b4f5034d 100644 (file)
@@ -91,7 +91,7 @@ int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */
 #define VS
 #endif
 
-#define IWLWIFI_VERSION "1.2.22k" VD VS
+#define IWLWIFI_VERSION "1.2.23k" VD VS
 #define DRV_COPYRIGHT  "Copyright(c) 2003-2007 Intel Corporation"
 #define DRV_VERSION     IWLWIFI_VERSION
 
@@ -687,6 +687,12 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c
        BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
               !(cmd->meta.flags & CMD_SIZE_HUGE));
 
+
+       if (iwl3945_is_rfkill(priv)) {
+               IWL_DEBUG_INFO("Not sending command - RF KILL");
+               return -EIO;
+       }
+
        if (iwl3945_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
                IWL_ERROR("No space for Tx\n");
                return -ENOSPC;
@@ -1557,6 +1563,20 @@ static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac)
        memcpy(mac, priv->eeprom.mac_address, 6);
 }
 
+/*
+ * Clear the OWNER_MSK, to establish driver (instead of uCode running on
+ * embedded controller) as EEPROM reader; each read is a series of pulses
+ * to/from the EEPROM chip, not a single event, so even reads could conflict
+ * if they weren't arbitrated by some ownership mechanism.  Here, the driver
+ * simply claims ownership, which should be safe when this function is called
+ * (i.e. before loading uCode!).
+ */
+static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv)
+{
+       _iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
+       return 0;
+}
+
 /**
  * iwl3945_eeprom_init - read EEPROM contents
  *
@@ -1566,7 +1586,7 @@ static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac)
  */
 int iwl3945_eeprom_init(struct iwl3945_priv *priv)
 {
-       __le16 *e = (__le16 *)&priv->eeprom;
+       u16 *e = (u16 *)&priv->eeprom;
        u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP);
        u32 r;
        int sz = sizeof(priv->eeprom);
@@ -1609,7 +1629,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
                        IWL_ERROR("Time out reading EEPROM[%d]", addr);
                        return -ETIMEDOUT;
                }
-               e[addr / 2] = cpu_to_le16(r >> 16);
+               e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
        }
 
        return 0;
@@ -2792,7 +2812,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
 #endif
 
        /* drop all data frame if we are not associated */
-       if (!iwl3945_is_associated(priv) && !priv->assoc_id &&
+       if ((!iwl3945_is_associated(priv) ||
+            ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id)) &&
            ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
                IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n");
                goto drop_unlock;
@@ -4193,13 +4214,13 @@ static u8 ratio2dB[100] = {
  * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
 int iwl3945_calc_db_from_ratio(int sig_ratio)
 {
-       /* Anything above 1000:1 just report as 60 dB */
-       if (sig_ratio > 1000)
+       /* 1000:1 or higher just report as 60 dB */
+       if (sig_ratio >= 1000)
                return 60;
 
-       /* Above 100:1, divide by 10 and use table,
+       /* 100:1 or higher, divide by 10 and use table,
         *   add 20 dB to make up for divide by 10 */
-       if (sig_ratio > 100)
+       if (sig_ratio >= 100)
                return (20 + (int)ratio2dB[sig_ratio/10]);
 
        /* We shouldn't see this */
@@ -4267,7 +4288,7 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
        int reclaim;
        unsigned long flags;
        u8 fill_rx = 0;
-       u32 count = 0;
+       u32 count = 8;
 
        /* uCode's read index (stored in shared DRAM) indicates the last Rx
         * buffer that the driver may process (last buffer filled by ucode). */
@@ -4745,8 +4766,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
 #ifdef CONFIG_IWL3945_DEBUG
        if (iwl3945_debug_level & (IWL_DL_ISR)) {
                /* NIC fires this, but we don't use it, redundant with WAKEUP */
-               if (inta & CSR_INT_BIT_MAC_CLK_ACTV)
-                       IWL_DEBUG_ISR("Microcode started or stopped.\n");
+               if (inta & CSR_INT_BIT_SCD)
+                       IWL_DEBUG_ISR("Scheduler finished to transmit "
+                                     "the frame/frames.\n");
 
                /* Alive notification via Rx interrupt will do the real work */
                if (inta & CSR_INT_BIT_ALIVE)
@@ -4754,7 +4776,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
        }
 #endif
        /* Safely ignore these bits for debug checks below */
-       inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE);
+       inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
 
        /* HW RF KILL switch toggled (4965 only) */
        if (inta & CSR_INT_BIT_RF_KILL) {
@@ -4890,8 +4912,11 @@ static irqreturn_t iwl3945_isr(int irq, void *data)
        IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
                      inta, inta_mask, inta_fh);
 
+       inta &= ~CSR_INT_BIT_SCD;
+
        /* iwl3945_irq_tasklet() will service interrupts and re-enable them */
-       tasklet_schedule(&priv->irq_tasklet);
+       if (likely(inta || inta_fh))
+               tasklet_schedule(&priv->irq_tasklet);
 unplugged:
        spin_unlock(&priv->lock);
 
@@ -5146,6 +5171,15 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
        return 0;
 }
 
+/*
+ * iwl3945_free_channel_map - undo allocations in iwl3945_init_channel_map
+ */
+static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
+{
+       kfree(priv->channel_info);
+       priv->channel_count = 0;
+}
+
 /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
  * sending probe req.  This should be set long enough to hear probe responses
  * from more than one AP.  */
@@ -5267,7 +5301,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
                        scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
                        /* NOTE: if we were doing 6Mb OFDM for scans we'd use
                         * power level:
-                        * scan_ch->tpc.tx_gain = ((1<<5) | (2 << 3)) | 3;
+                        * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
                         */
                }
 
@@ -5471,6 +5505,17 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv)
        return 0;
 }
 
+/*
+ * iwl3945_free_geos - undo allocations in iwl3945_init_geos
+ */
+static void iwl3945_free_geos(struct iwl3945_priv *priv)
+{
+       kfree(priv->modes);
+       kfree(priv->ieee_channels);
+       kfree(priv->ieee_rates);
+       clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+}
+
 /******************************************************************************
  *
  * uCode download functions
@@ -5479,48 +5524,12 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv)
 
 static void iwl3945_dealloc_ucode_pci(struct iwl3945_priv *priv)
 {
-       if (priv->ucode_code.v_addr != NULL) {
-               pci_free_consistent(priv->pci_dev,
-                                   priv->ucode_code.len,
-                                   priv->ucode_code.v_addr,
-                                   priv->ucode_code.p_addr);
-               priv->ucode_code.v_addr = NULL;
-       }
-       if (priv->ucode_data.v_addr != NULL) {
-               pci_free_consistent(priv->pci_dev,
-                                   priv->ucode_data.len,
-                                   priv->ucode_data.v_addr,
-                                   priv->ucode_data.p_addr);
-               priv->ucode_data.v_addr = NULL;
-       }
-       if (priv->ucode_data_backup.v_addr != NULL) {
-               pci_free_consistent(priv->pci_dev,
-                                   priv->ucode_data_backup.len,
-                                   priv->ucode_data_backup.v_addr,
-                                   priv->ucode_data_backup.p_addr);
-               priv->ucode_data_backup.v_addr = NULL;
-       }
-       if (priv->ucode_init.v_addr != NULL) {
-               pci_free_consistent(priv->pci_dev,
-                                   priv->ucode_init.len,
-                                   priv->ucode_init.v_addr,
-                                   priv->ucode_init.p_addr);
-               priv->ucode_init.v_addr = NULL;
-       }
-       if (priv->ucode_init_data.v_addr != NULL) {
-               pci_free_consistent(priv->pci_dev,
-                                   priv->ucode_init_data.len,
-                                   priv->ucode_init_data.v_addr,
-                                   priv->ucode_init_data.p_addr);
-               priv->ucode_init_data.v_addr = NULL;
-       }
-       if (priv->ucode_boot.v_addr != NULL) {
-               pci_free_consistent(priv->pci_dev,
-                                   priv->ucode_boot.len,
-                                   priv->ucode_boot.v_addr,
-                                   priv->ucode_boot.p_addr);
-               priv->ucode_boot.v_addr = NULL;
-       }
+       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
+       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
+       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init);
+       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
 }
 
 /**
@@ -5817,12 +5826,6 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv)
        iwl3945_write32(priv, CSR_RESET, 0);
 }
 
-static int iwl3945_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
-{
-       desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr);
-       return (desc->v_addr != NULL) ? 0 : -ENOMEM;
-}
-
 /**
  * iwl3945_read_ucode - Read uCode images from disk file.
  *
@@ -5925,13 +5928,13 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
         * 1) unmodified from disk
         * 2) backup cache for save/restore during power-downs */
        priv->ucode_code.len = inst_size;
-       iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
+       iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
 
        priv->ucode_data.len = data_size;
-       iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
+       iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
 
        priv->ucode_data_backup.len = data_size;
-       iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+       iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
 
        if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
            !priv->ucode_data_backup.v_addr)
@@ -5940,10 +5943,10 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
        /* Initialization instructions and data */
        if (init_size && init_data_size) {
                priv->ucode_init.len = init_size;
-               iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
+               iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
 
                priv->ucode_init_data.len = init_data_size;
-               iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+               iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
 
                if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
                        goto err_pci_alloc;
@@ -5952,7 +5955,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
        /* Bootstrap (instructions only, no data) */
        if (boot_size) {
                priv->ucode_boot.len = boot_size;
-               iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
+               iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
 
                if (!priv->ucode_boot.v_addr)
                        goto err_pci_alloc;
@@ -6172,15 +6175,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
        /* Clear out the uCode error bit if it is set */
        clear_bit(STATUS_FW_ERROR, &priv->status);
 
-       rc = iwl3945_init_channel_map(priv);
-       if (rc) {
-               IWL_ERROR("initializing regulatory failed: %d\n", rc);
-               return;
-       }
-
-       iwl3945_init_geos(priv);
-       iwl3945_reset_channel_flag(priv);
-
        if (iwl3945_is_rfkill(priv))
                return;
 
@@ -6269,6 +6263,8 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
                                        STATUS_RF_KILL_HW |
                               test_bit(STATUS_RF_KILL_SW, &priv->status) <<
                                        STATUS_RF_KILL_SW |
+                              test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
+                                       STATUS_GEO_CONFIGURED |
                               test_bit(STATUS_IN_SUSPEND, &priv->status) <<
                                        STATUS_IN_SUSPEND;
                goto exit;
@@ -6280,6 +6276,8 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
                                STATUS_RF_KILL_HW |
                        test_bit(STATUS_RF_KILL_SW, &priv->status) <<
                                STATUS_RF_KILL_SW |
+                       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
+                               STATUS_GEO_CONFIGURED |
                        test_bit(STATUS_IN_SUSPEND, &priv->status) <<
                                STATUS_IN_SUSPEND |
                        test_bit(STATUS_FW_ERROR, &priv->status) <<
@@ -6340,7 +6338,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
        if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
                IWL_WARNING("Radio disabled by SW RF kill (module "
                            "parameter)\n");
-               return 0;
+               return -ENODEV;
        }
 
        if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
@@ -6348,6 +6346,18 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
                return -EIO;
        }
 
+       /* If platform's RF_KILL switch is NOT set to KILL */
+       if (iwl3945_read32(priv, CSR_GP_CNTRL) &
+                               CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+               clear_bit(STATUS_RF_KILL_HW, &priv->status);
+       else {
+               set_bit(STATUS_RF_KILL_HW, &priv->status);
+               if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
+                       IWL_WARNING("Radio disabled by HW RF Kill switch\n");
+                       return -ENODEV;
+               }
+       }
+
        iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
 
        rc = iwl3945_hw_nic_init(priv);
@@ -6375,6 +6385,10 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
        memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
               priv->ucode_data.len);
 
+       /* We return success when we resume from suspend and rf_kill is on. */
+       if (test_bit(STATUS_RF_KILL_HW, &priv->status))
+               return 0;
+
        for (i = 0; i < MAX_HW_RESTARTS; i++) {
 
                iwl3945_clear_stations_table(priv);
@@ -6625,7 +6639,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
         * that based on the direct_mask added to each channel entry */
        scan->tx_cmd.len = cpu_to_le16(
                iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
-                       IWL_MAX_SCAN_SIZE - sizeof(scan), 0));
+                       IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
        scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
        scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
        scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
@@ -6919,12 +6933,18 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
                }
        }
 
-       IWL_DEBUG_INFO("Start UP work.\n");
-       __iwl3945_up(priv);
+       ret = __iwl3945_up(priv);
 
-       priv->is_open = 1;
        mutex_unlock(&priv->mutex);
 
+       if (ret)
+               goto out_release_irq;
+
+       IWL_DEBUG_INFO("Start UP work.\n");
+
+       if (test_bit(STATUS_IN_SUSPEND, &priv->status))
+               return 0;
+
        /* Wait for START_ALIVE from ucode. Otherwise callbacks from
         * mac80211 will not be run successfully. */
        ret = wait_event_interruptible_timeout(priv->wait_command_queue,
@@ -6939,6 +6959,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
                }
        }
 
+       priv->is_open = 1;
        IWL_DEBUG_MAC80211("leave\n");
        return 0;
 
@@ -6946,6 +6967,9 @@ out_release_irq:
        free_irq(priv->pci_dev->irq, priv);
 out_disable_msi:
        pci_disable_msi(priv->pci_dev);
+       pci_disable_device(priv->pci_dev);
+       priv->is_open = 0;
+       IWL_DEBUG_MAC80211("leave - failed\n");
        return ret;
 }
 
@@ -6955,12 +6979,17 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
 
        IWL_DEBUG_MAC80211("enter\n");
 
-       /* stop mac, cancel any scan request and clear
-        * RXON_FILTER_ASSOC_MSK BIT
-        */
+       if (!priv->is_open) {
+               IWL_DEBUG_MAC80211("leave - skip\n");
+               return;
+       }
+
        priv->is_open = 0;
 
        if (iwl3945_is_ready_rf(priv)) {
+               /* stop mac, cancel any scan request and clear
+                * RXON_FILTER_ASSOC_MSK BIT
+                */
                mutex_lock(&priv->mutex);
                iwl3945_scan_cancel_timeout(priv, 100);
                cancel_delayed_work(&priv->post_associate);
@@ -7131,7 +7160,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
 {
        int rc = 0;
 
-       if (priv->status & STATUS_EXIT_PENDING)
+       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
        /* The following should be done only at AP bring up */
@@ -7334,7 +7363,6 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
        mutex_unlock(&priv->mutex);
 
        IWL_DEBUG_MAC80211("leave\n");
-
 }
 
 static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
@@ -8626,11 +8654,24 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
        SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 
+       err = iwl3945_init_channel_map(priv);
+       if (err) {
+               IWL_ERROR("initializing regulatory failed: %d\n", err);
+               goto out_remove_sysfs;
+       }
+
+       err = iwl3945_init_geos(priv);
+       if (err) {
+               IWL_ERROR("initializing geos failed: %d\n", err);
+               goto out_free_channel_map;
+       }
+       iwl3945_reset_channel_flag(priv);
+
        iwl3945_rate_control_register(priv->hw);
        err = ieee80211_register_hw(priv->hw);
        if (err) {
                IWL_ERROR("Failed to register network device (error %d)\n", err);
-               goto out_remove_sysfs;
+               goto out_free_geos;
        }
 
        priv->hw->conf.beacon_int = 100;
@@ -8640,6 +8681,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        return 0;
 
+ out_free_geos:
+       iwl3945_free_geos(priv);
+ out_free_channel_map:
+       iwl3945_free_channel_map(priv);
  out_remove_sysfs:
        sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
@@ -8714,10 +8759,8 @@ static void iwl3945_pci_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
 
-       kfree(priv->channel_info);
-
-       kfree(priv->ieee_channels);
-       kfree(priv->ieee_rates);
+       iwl3945_free_channel_map(priv);
+       iwl3945_free_geos(priv);
 
        if (priv->ibss_beacon)
                dev_kfree_skb(priv->ibss_beacon);
@@ -8731,89 +8774,27 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct iwl3945_priv *priv = pci_get_drvdata(pdev);
 
-       set_bit(STATUS_IN_SUSPEND, &priv->status);
-
-       /* Take down the device; powers it off, etc. */
-       iwl3945_down(priv);
-
-       if (priv->mac80211_registered)
-               ieee80211_stop_queues(priv->hw);
+       if (priv->is_open) {
+               set_bit(STATUS_IN_SUSPEND, &priv->status);
+               iwl3945_mac_stop(priv->hw);
+               priv->is_open = 1;
+       }
 
-       pci_save_state(pdev);
-       pci_disable_device(pdev);
        pci_set_power_state(pdev, PCI_D3hot);
 
        return 0;
 }
 
-static void iwl3945_resume(struct iwl3945_priv *priv)
-{
-       unsigned long flags;
-
-       /* The following it a temporary work around due to the
-        * suspend / resume not fully initializing the NIC correctly.
-        * Without all of the following, resume will not attempt to take
-        * down the NIC (it shouldn't really need to) and will just try
-        * and bring the NIC back up.  However that fails during the
-        * ucode verification process.  This then causes iwl3945_down to be
-        * called *after* iwl3945_hw_nic_init() has succeeded -- which
-        * then lets the next init sequence succeed.  So, we've
-        * replicated all of that NIC init code here... */
-
-       iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
-
-       iwl3945_hw_nic_init(priv);
-
-       iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-       iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-                   CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-       iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
-       iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-       iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
-       /* tell the device to stop sending interrupts */
-       iwl3945_disable_interrupts(priv);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
-       if (!iwl3945_grab_nic_access(priv)) {
-               iwl3945_write_prph(priv, APMG_CLK_DIS_REG,
-                                        APMG_CLK_VAL_DMA_CLK_RQT);
-               iwl3945_release_nic_access(priv);
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       udelay(5);
-
-       iwl3945_hw_nic_reset(priv);
-
-       /* Bring the device back up */
-       clear_bit(STATUS_IN_SUSPEND, &priv->status);
-       queue_work(priv->workqueue, &priv->up);
-}
-
 static int iwl3945_pci_resume(struct pci_dev *pdev)
 {
        struct iwl3945_priv *priv = pci_get_drvdata(pdev);
-       int err;
-
-       printk(KERN_INFO "Coming out of suspend...\n");
 
        pci_set_power_state(pdev, PCI_D0);
-       err = pci_enable_device(pdev);
-       pci_restore_state(pdev);
-
-       /*
-        * Suspend/Resume resets the PCI configuration space, so we have to
-        * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
-        * from interfering with C3 CPU state. pci_restore_state won't help
-        * here since it only restores the first 64 bytes pci config header.
-        */
-       pci_write_config_byte(pdev, 0x41, 0x00);
 
-       iwl3945_resume(priv);
+       if (priv->is_open)
+               iwl3945_mac_start(priv->hw);
 
+       clear_bit(STATUS_IN_SUSPEND, &priv->status);
        return 0;
 }