iwlwifi: earlier rx allocation
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / iwlwifi / iwl3945-base.c
index 76186f85c13164327ae9fc3eec48f5fea0bf4155..74b1099ff8aa27506aec01d3f97f0b6ad5832088 100644 (file)
  *
  *****************************************************************************/
 
-/*
- * NOTE:  This file (iwl-base.c) is used to build to multiple hardware targets
- * by defining IWL to either 3945 or 4965.  The Makefile used when building
- * the base targets will create base-3945.o and base-4965.o
- *
- * The eventual goal is to move as many of the #if IWL / #endif blocks out of
- * this file and into the hardware specific implementation files (iwl-XXXX.c)
- * and leave only the common (non #ifdef sprinkled) code in this file
- */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/version.h>
@@ -73,13 +63,13 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv,
  ******************************************************************************/
 
 /* module parameters */
-static int iwl3945_param_disable_hw_scan;
-static int iwl3945_param_debug;
-static int iwl3945_param_disable;      /* def: enable radio */
-static int iwl3945_param_antenna;      /* def: 0 = both antennas (use diversity) */
-int iwl3945_param_hwcrypto;     /* def: using software encryption */
-static int iwl3945_param_qos_enable = 1;
-int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES;
+static int iwl3945_param_disable_hw_scan; /* def: 0 = use 3945's h/w scan */
+static int iwl3945_param_debug;    /* def: 0 = minimal debug log messages */
+static int iwl3945_param_disable;  /* def: 0 = enable radio */
+static int iwl3945_param_antenna;  /* def: 0 = both antennas (use diversity) */
+int iwl3945_param_hwcrypto;        /* def: 0 = use software encryption */
+static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */
+int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */
 
 /*
  * module name, copyright, version, etc.
@@ -101,7 +91,7 @@ int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES;
 #define VS
 #endif
 
-#define IWLWIFI_VERSION "1.1.19k" VD VS
+#define IWLWIFI_VERSION "1.2.23k" VD VS
 #define DRV_COPYRIGHT  "Copyright(c) 2003-2007 Intel Corporation"
 #define DRV_VERSION     IWLWIFI_VERSION
 
@@ -194,17 +184,24 @@ static void iwl3945_print_hex_dump(int level, void *p, u32 len)
  *
  * Theory of operation
  *
- * A queue is a circular buffers with 'Read' and 'Write' pointers.
- * 2 empty entries always kept in the buffer to protect from overflow.
+ * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
+ * of buffer descriptors, each of which points to one or more data buffers for
+ * the device to read from or fill.  Driver and device exchange status of each
+ * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
+ * entries in each circular buffer, to protect against confusing empty and full
+ * queue states.
+ *
+ * The device reads or writes the data in the queues via the device's several
+ * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
  *
  * For Tx queue, there are low mark and high mark limits. If, after queuing
  * the packet for Tx, free space become < low mark, Tx queue stopped. When
  * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
  * Tx queue resumed.
  *
- * The IWL operates with six queues, one receive queue in the device's
- * sram, one transmit queue for sending commands to the device firmware,
- * and four transmit queues for data.
+ * The 3945 operates with six queues:  One receive queue, one transmit queue
+ * (#4) for sending commands to the device firmware, and four transmit queues
+ * (#0-3) for data tx via EDCA.  An additional 2 HCCA queues are unused.
  ***************************************************/
 
 static int iwl3945_queue_space(const struct iwl3945_queue *q)
@@ -223,13 +220,21 @@ static int iwl3945_queue_space(const struct iwl3945_queue *q)
        return s;
 }
 
-/* XXX: n_bd must be power-of-two size */
+/**
+ * iwl3945_queue_inc_wrap - increment queue index, wrap back to beginning
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
 static inline int iwl3945_queue_inc_wrap(int index, int n_bd)
 {
        return ++index & (n_bd - 1);
 }
 
-/* XXX: n_bd must be power-of-two size */
+/**
+ * iwl3945_queue_dec_wrap - increment queue index, wrap back to end
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
 static inline int iwl3945_queue_dec_wrap(int index, int n_bd)
 {
        return --index & (n_bd - 1);
@@ -244,12 +249,17 @@ static inline int x2_queue_used(const struct iwl3945_queue *q, int i)
 
 static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge)
 {
+       /* This is for scan command, the big buffer at end of command array */
        if (is_huge)
-               return q->n_window;
+               return q->n_window;     /* must be power of 2 */
 
+       /* Otherwise, use normal size buffers */
        return index & (q->n_window - 1);
 }
 
+/**
+ * iwl3945_queue_init - Initialize queue's high/low-water and read/write indexes
+ */
 static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q,
                          int count, int slots_num, u32 id)
 {
@@ -278,11 +288,16 @@ static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q
        return 0;
 }
 
+/**
+ * iwl3945_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
+ */
 static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv,
                              struct iwl3945_tx_queue *txq, u32 id)
 {
        struct pci_dev *dev = priv->pci_dev;
 
+       /* Driver private data, only for Tx (not command) queues,
+        * not shared with device. */
        if (id != IWL_CMD_QUEUE_NUM) {
                txq->txb = kmalloc(sizeof(txq->txb[0]) *
                                   TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
@@ -294,6 +309,8 @@ static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv,
        } else
                txq->txb = NULL;
 
+       /* Circular buffer of transmit frame descriptors (TFDs),
+        * shared with device */
        txq->bd = pci_alloc_consistent(dev,
                        sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
                        &txq->q.dma_addr);
@@ -316,6 +333,9 @@ static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv,
        return -ENOMEM;
 }
 
+/**
+ * iwl3945_tx_queue_init - Allocate and initialize one tx/cmd queue
+ */
 int iwl3945_tx_queue_init(struct iwl3945_priv *priv,
                      struct iwl3945_tx_queue *txq, int slots_num, u32 txq_id)
 {
@@ -323,9 +343,14 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv,
        int len;
        int rc = 0;
 
-       /* allocate command space + one big command for scan since scan
-        * command is very huge the system will not have two scan at the
-        * same time */
+       /*
+        * Alloc buffer array for commands (Tx or other types of commands).
+        * For the command queue (#4), allocate command space + one big
+        * command for scan, since scan command is very huge; the system will
+        * not have two scans at the same time, so only one is needed.
+        * For data Tx queues (all other queues), no super-size command
+        * space is needed.
+        */
        len = sizeof(struct iwl3945_cmd) * slots_num;
        if (txq_id == IWL_CMD_QUEUE_NUM)
                len +=  IWL_MAX_SCAN_SIZE;
@@ -333,6 +358,7 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv,
        if (!txq->cmd)
                return -ENOMEM;
 
+       /* Alloc driver data array and TFD circular buffer */
        rc = iwl3945_tx_queue_alloc(priv, txq, txq_id);
        if (rc) {
                pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
@@ -344,8 +370,11 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv,
        /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
         * iwl3945_queue_inc_wrap and iwl3945_queue_dec_wrap are broken. */
        BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+
+       /* Initialize queue high/low-water, head/tail indexes */
        iwl3945_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
 
+       /* Tell device where to find queue, enable DMA channel. */
        iwl3945_hw_tx_queue_init(priv, txq);
 
        return 0;
@@ -356,8 +385,8 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv,
  * @txq: Transmit queue to deallocate.
  *
  * Empty queue by removing and destroying all BD's.
- * Free all buffers.  txq itself is not freed.
- *
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
  */
 void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq)
 {
@@ -377,35 +406,38 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t
        if (q->id == IWL_CMD_QUEUE_NUM)
                len += IWL_MAX_SCAN_SIZE;
 
+       /* De-alloc array of command/tx buffers */
        pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
 
-       /* free buffers belonging to queue itself */
+       /* De-alloc circular buffer of TFDs */
        if (txq->q.n_bd)
                pci_free_consistent(dev, sizeof(struct iwl3945_tfd_frame) *
                                    txq->q.n_bd, txq->bd, txq->q.dma_addr);
 
+       /* De-alloc array of per-TFD driver data */
        if (txq->txb) {
                kfree(txq->txb);
                txq->txb = NULL;
        }
 
-       /* 0 fill whole structure */
+       /* 0-fill queue descriptor structure */
        memset(txq, 0, sizeof(*txq));
 }
 
 const u8 iwl3945_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 
 /*************** STATION TABLE MANAGEMENT ****
- *
- * NOTE:  This needs to be overhauled to better synchronize between
- * how the iwl-4965.c is using iwl3945_hw_find_station vs. iwl-3945.c
- *
- * mac80211 should also be examined to determine if sta_info is duplicating
+ * mac80211 should be examined to determine if sta_info is duplicating
  * the functionality provided here
  */
 
 /**************************************************************/
 #if 0 /* temporary disable till we add real remove station */
+/**
+ * iwl3945_remove_station - Remove driver's knowledge of station.
+ *
+ * NOTE:  This does not remove station from device's station table.
+ */
 static u8 iwl3945_remove_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap)
 {
        int index = IWL_INVALID_STATION;
@@ -442,6 +474,12 @@ out:
        return 0;
 }
 #endif
+
+/**
+ * iwl3945_clear_stations_table - Clear the driver's station table
+ *
+ * NOTE:  This does not clear or otherwise alter the device's station table.
+ */
 static void iwl3945_clear_stations_table(struct iwl3945_priv *priv)
 {
        unsigned long flags;
@@ -454,7 +492,9 @@ static void iwl3945_clear_stations_table(struct iwl3945_priv *priv)
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
 
-
+/**
+ * iwl3945_add_station - Add station to station tables in driver and device
+ */
 u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 flags)
 {
        int i;
@@ -500,6 +540,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
        station->used = 1;
        priv->num_stations++;
 
+       /* Set up the REPLY_ADD_STA command to send to device */
        memset(&station->sta, 0, sizeof(struct iwl3945_addsta_cmd));
        memcpy(station->sta.sta.addr, addr, ETH_ALEN);
        station->sta.mode = 0;
@@ -518,6 +559,8 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
                        le16_to_cpu(station->sta.rate_n_flags);
 
        spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
+       /* Add station to device's station table */
        iwl3945_send_add_station(priv, &station->sta, flags);
        return index;
 
@@ -644,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;
@@ -687,6 +736,8 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c
                     fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
 
        txq->need_update = 1;
+
+       /* Increment and update queue's write index */
        q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd);
        ret = iwl3945_tx_queue_update_write_ptr(priv, txq);
 
@@ -956,12 +1007,12 @@ static int iwl3945_check_rxon_cmd(struct iwl3945_rxon_cmd *rxon)
 }
 
 /**
- * iwl3945_full_rxon_required - determine if RXON_ASSOC can be used in RXON commit
+ * iwl3945_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
  * @priv: staging_rxon is compared to active_rxon
  *
- * If the RXON structure is changing sufficient to require a new
- * tune or to clear and reset the RXON_FILTER_ASSOC_MSK then return 1
- * to indicate a new tune is required.
+ * If the RXON structure is changing enough to require a new tune,
+ * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
+ * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
  */
 static int iwl3945_full_rxon_required(struct iwl3945_priv *priv)
 {
@@ -1235,7 +1286,7 @@ static int iwl3945_card_state_sync_callback(struct iwl3945_priv *priv,
 /*
  * CARD_STATE_CMD
  *
- * Use: Sets the internal card state to enable, disable, or halt
+ * Use: Sets the device's internal card state to enable, disable, or halt
  *
  * When in the 'enable' state the card operates as normal.
  * When in the 'disable' state, the card enters into a low power mode.
@@ -1452,16 +1503,6 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
        return priv->ibss_beacon->len;
 }
 
-static int iwl3945_rate_index_from_plcp(int plcp)
-{
-       int i = 0;
-
-       for (i = 0; i < IWL_RATE_COUNT; i++)
-               if (iwl3945_rates[i].plcp == plcp)
-                       return i;
-       return -1;
-}
-
 static u8 iwl3945_rate_get_lowest_plcp(int rate_mask)
 {
        u8 i;
@@ -1522,16 +1563,30 @@ 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
  *
- * Load the EEPROM from adapter into priv->eeprom
+ * Load the EEPROM contents from adapter into priv->eeprom
  *
  * NOTE:  This routine uses the non-debug IO access functions.
  */
 int iwl3945_eeprom_init(struct iwl3945_priv *priv)
 {
-       u16 *e = (u16 *)&priv->eeprom;
+       __le16 *e = (__le16 *)&priv->eeprom;
        u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP);
        u32 r;
        int sz = sizeof(priv->eeprom);
@@ -1550,6 +1605,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
                return -ENOENT;
        }
 
+       /* Make sure driver (instead of uCode) is allowed to read EEPROM */
        rc = iwl3945_eeprom_acquire_semaphore(priv);
        if (rc < 0) {
                IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
@@ -1573,7 +1629,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
                        IWL_ERROR("Time out reading EEPROM[%d]", addr);
                        return -ETIMEDOUT;
                }
-               e[addr / 2] = le16_to_cpu(r >> 16);
+               e[addr / 2] = cpu_to_le16(r >> 16);
        }
 
        return 0;
@@ -1589,14 +1645,9 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
 /**
  * iwl3945_report_frame - dump frame to syslog during debug sessions
  *
- * hack this function to show different aspects of received frames,
+ * You may hack this function to show different aspects of received frames,
  * including selective frame dumps.
  * group100 parameter selects whether to show 1 out of 100 good frames.
- *
- * TODO:  ieee80211_hdr stuff is common to 3945 and 4965, so frame type
- *        info output is okay, but some of this stuff (e.g. iwl3945_rx_frame_stats)
- *        is 3945-specific and gives bad output for 4965.  Need to split the
- *        functionality, keep common stuff here.
  */
 void iwl3945_report_frame(struct iwl3945_priv *priv,
                      struct iwl3945_rx_packet *pkt,
@@ -2505,9 +2556,6 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
 
 static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
 {
-       if (!iwl3945_is_ready_rf(priv))
-               return -EAGAIN;
-
        if (mode == IEEE80211_IF_TYPE_IBSS) {
                const struct iwl3945_channel_info *ch_info;
 
@@ -2522,13 +2570,6 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
                }
        }
 
-       cancel_delayed_work(&priv->scan_check);
-       if (iwl3945_scan_cancel_timeout(priv, 100)) {
-               IWL_WARNING("Aborted scan still in progress after 100ms\n");
-               IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
-               return -EAGAIN;
-       }
-
        priv->iw_mode = mode;
 
        iwl3945_connection_init_rx_config(priv);
@@ -2536,6 +2577,17 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
 
        iwl3945_clear_stations_table(priv);
 
+       /* dont commit rxon if rf-kill is on*/
+       if (!iwl3945_is_ready_rf(priv))
+               return -EAGAIN;
+
+       cancel_delayed_work(&priv->scan_check);
+       if (iwl3945_scan_cancel_timeout(priv, 100)) {
+               IWL_WARNING("Aborted scan still in progress after 100ms\n");
+               IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
+               return -EAGAIN;
+       }
+
        iwl3945_commit_rxon(priv);
 
        return 0;
@@ -2650,21 +2702,23 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
        cmd->cmd.tx.next_frame_len = 0;
 }
 
+/**
+ * iwl3945_get_sta_id - Find station's index within station table
+ */
 static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *hdr)
 {
        int sta_id;
        u16 fc = le16_to_cpu(hdr->frame_control);
 
-       /* If this frame is broadcast or not data then use the broadcast
-        * station id */
+       /* If this frame is broadcast or management, use broadcast station id */
        if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
            is_multicast_ether_addr(hdr->addr1))
                return priv->hw_setting.bcast_sta_id;
 
        switch (priv->iw_mode) {
 
-       /* If this frame is part of a BSS network (we're a station), then
-        * we use the AP's station id */
+       /* If we are a client station in a BSS network, use the special
+        * AP station entry (that's the only station we communicate with) */
        case IEEE80211_IF_TYPE_STA:
                return IWL_AP_ID;
 
@@ -2675,11 +2729,12 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
                        return sta_id;
                return priv->hw_setting.bcast_sta_id;
 
-       /* If this frame is part of a IBSS network, then we use the
-        * target specific station id */
+       /* If this frame is going out to an IBSS network, find the station,
+        * or create a new station table entry */
        case IEEE80211_IF_TYPE_IBSS: {
                DECLARE_MAC_BUF(mac);
 
+               /* Create new station table entry */
                sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
                if (sta_id != IWL_INVALID_STATION)
                        return sta_id;
@@ -2732,8 +2787,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
                goto drop_unlock;
        }
 
-       if (!priv->interface_id) {
-               IWL_DEBUG_DROP("Dropping - !priv->interface_id\n");
+       if (!priv->vif) {
+               IWL_DEBUG_DROP("Dropping - !priv->vif\n");
                goto drop_unlock;
        }
 
@@ -2756,7 +2811,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
                IWL_DEBUG_TX("Sending REASSOC frame\n");
 #endif
 
-       if (!iwl3945_is_associated(priv) &&
+       /* drop all data frame if we are not associated */
+       if ((!iwl3945_is_associated(priv) || !priv->assoc_id) &&
            ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
                IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n");
                goto drop_unlock;
@@ -2765,6 +2821,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
        spin_unlock_irqrestore(&priv->lock, flags);
 
        hdr_len = ieee80211_get_hdrlen(fc);
+
+       /* Find (or create) index into station table for destination station */
        sta_id = iwl3945_get_sta_id(priv, hdr);
        if (sta_id == IWL_INVALID_STATION) {
                DECLARE_MAC_BUF(mac);
@@ -2786,30 +2844,52 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
                                __constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
                seq_number += 0x10;
        }
+
+       /* Descriptor for chosen Tx queue */
        txq = &priv->txq[txq_id];
        q = &txq->q;
 
        spin_lock_irqsave(&priv->lock, flags);
 
+       /* Set up first empty TFD within this queue's circular TFD buffer */
        tfd = &txq->bd[q->write_ptr];
        memset(tfd, 0, sizeof(*tfd));
        control_flags = (u32 *) tfd;
        idx = get_cmd_index(q, q->write_ptr, 0);
 
+       /* Set up driver data for this TFD */
        memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl3945_tx_info));
        txq->txb[q->write_ptr].skb[0] = skb;
        memcpy(&(txq->txb[q->write_ptr].status.control),
               ctl, sizeof(struct ieee80211_tx_control));
+
+       /* Init first empty entry in queue's array of Tx/cmd buffers */
        out_cmd = &txq->cmd[idx];
        memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
        memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx));
+
+       /*
+        * Set up the Tx-command (not MAC!) header.
+        * Store the chosen Tx queue and TFD index within the sequence field;
+        * after Tx, uCode's Tx response will return this value so driver can
+        * locate the frame within the tx queue and do post-tx processing.
+        */
        out_cmd->hdr.cmd = REPLY_TX;
        out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
                                INDEX_TO_SEQ(q->write_ptr)));
-       /* copy frags header */
+
+       /* Copy MAC header from skb into command buffer */
        memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len);
 
-       /* hdr = (struct ieee80211_hdr *)out_cmd->cmd.tx.hdr; */
+       /*
+        * Use the first empty entry in this queue's command buffer array
+        * to contain the Tx command and MAC header concatenated together
+        * (payload data will be in another buffer).
+        * Size of this varies, due to varying MAC header length.
+        * If end is not dword aligned, we'll have 2 extra bytes at the end
+        * of the MAC header (device reads on dword boundaries).
+        * We'll tell device about this padding later.
+        */
        len = priv->hw_setting.tx_cmd_len +
                sizeof(struct iwl3945_cmd_header) + hdr_len;
 
@@ -2821,15 +2901,20 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
        else
                len_org = 0;
 
+       /* Physical address of this Tx command's header (not MAC header!),
+        * within command buffer array. */
        txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl3945_cmd) * idx +
                     offsetof(struct iwl3945_cmd, hdr);
 
+       /* Add buffer containing Tx command and MAC(!) header to TFD's
+        * first entry */
        iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
 
        if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
                iwl3945_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
 
-       /* 802.11 null functions have no payload... */
+       /* Set up TFD's 2nd entry to point directly to remainder of skb,
+        * if any (802.11 null frames have no payload). */
        len = skb->len - hdr_len;
        if (len) {
                phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
@@ -2837,13 +2922,16 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
                iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
        }
 
-       /* If there is no payload, then only one TFD is used */
        if (!len)
+               /* If there is no payload, then we use only one Tx buffer */
                *control_flags = TFD_CTL_COUNT_SET(1);
        else
+               /* Else use 2 buffers.
+                * Tell 3945 about any padding after MAC header */
                *control_flags = TFD_CTL_COUNT_SET(2) |
                        TFD_CTL_PAD_SET(U32_PAD(len));
 
+       /* Total # bytes to be transmitted */
        len = (u16)skb->len;
        out_cmd->cmd.tx.len = cpu_to_le16(len);
 
@@ -2873,6 +2961,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
        iwl3945_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
                           ieee80211_get_hdrlen(fc));
 
+       /* Tell device the write index *just past* this latest filled TFD */
        q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd);
        rc = iwl3945_tx_queue_update_write_ptr(priv, txq);
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -3042,94 +3131,6 @@ void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb,
        }
 }
 
-void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv,
-                                   struct iwl3945_rx_mem_buffer *rxb,
-                                   void *data, short len,
-                                   struct ieee80211_rx_status *stats,
-                                   u16 phy_flags)
-{
-       struct iwl3945_rt_rx_hdr *iwl3945_rt;
-
-       /* First cache any information we need before we overwrite
-        * the information provided in the skb from the hardware */
-       s8 signal = stats->ssi;
-       s8 noise = 0;
-       int rate = stats->rate;
-       u64 tsf = stats->mactime;
-       __le16 phy_flags_hw = cpu_to_le16(phy_flags);
-
-       /* We received data from the HW, so stop the watchdog */
-       if (len > IWL_RX_BUF_SIZE - sizeof(*iwl3945_rt)) {
-               IWL_DEBUG_DROP("Dropping too large packet in monitor\n");
-               return;
-       }
-
-       /* copy the frame data to write after where the radiotap header goes */
-       iwl3945_rt = (void *)rxb->skb->data;
-       memmove(iwl3945_rt->payload, data, len);
-
-       iwl3945_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
-       iwl3945_rt->rt_hdr.it_pad = 0; /* always good to zero */
-
-       /* total header + data */
-       iwl3945_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*iwl3945_rt));
-
-       /* Set the size of the skb to the size of the frame */
-       skb_put(rxb->skb, sizeof(*iwl3945_rt) + len);
-
-       /* Big bitfield of all the fields we provide in radiotap */
-       iwl3945_rt->rt_hdr.it_present =
-           cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
-                       (1 << IEEE80211_RADIOTAP_FLAGS) |
-                       (1 << IEEE80211_RADIOTAP_RATE) |
-                       (1 << IEEE80211_RADIOTAP_CHANNEL) |
-                       (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
-                       (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
-                       (1 << IEEE80211_RADIOTAP_ANTENNA));
-
-       /* Zero the flags, we'll add to them as we go */
-       iwl3945_rt->rt_flags = 0;
-
-       iwl3945_rt->rt_tsf = cpu_to_le64(tsf);
-
-       /* Convert to dBm */
-       iwl3945_rt->rt_dbmsignal = signal;
-       iwl3945_rt->rt_dbmnoise = noise;
-
-       /* Convert the channel frequency and set the flags */
-       iwl3945_rt->rt_channelMHz = cpu_to_le16(stats->freq);
-       if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
-               iwl3945_rt->rt_chbitmask =
-                   cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ));
-       else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
-               iwl3945_rt->rt_chbitmask =
-                   cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
-       else    /* 802.11g */
-               iwl3945_rt->rt_chbitmask =
-                   cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ));
-
-       rate = iwl3945_rate_index_from_plcp(rate);
-       if (rate == -1)
-               iwl3945_rt->rt_rate = 0;
-       else
-               iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee;
-
-       /* antenna number */
-       iwl3945_rt->rt_antenna =
-               le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
-
-       /* set the preamble flag if we have it */
-       if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
-               iwl3945_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
-
-       IWL_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
-
-       stats->flag |= RX_FLAG_RADIOTAP;
-       ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
-       rxb->skb = NULL;
-}
-
-
 #define IWL_PACKET_RETRY_TIME HZ
 
 int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header)
@@ -3348,11 +3349,11 @@ static void iwl3945_txstatus_to_ieee(struct iwl3945_priv *priv,
 }
 
 /**
- * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries no more used by NIC.
+ * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
  *
- * When FW advances 'R' index, all entries between old and
- * new 'R' index need to be reclaimed. As result, some free space
- * forms. If there is enough free space (> low mark), wake Tx queue.
+ * When FW advances 'R' index, all entries between old and new 'R' index
+ * need to be reclaimed. As result, some free space forms. If there is
+ * enough free space (> low mark), wake the stack that feeds us.
  */
 static int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index)
 {
@@ -3401,6 +3402,9 @@ static int iwl3945_is_tx_success(u32 status)
  * Generic RX handler implementations
  *
  ******************************************************************************/
+/**
+ * iwl3945_rx_reply_tx - Handle Tx response
+ */
 static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
                            struct iwl3945_rx_mem_buffer *rxb)
 {
@@ -3565,7 +3569,7 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
        struct sk_buff *beacon;
 
        /* Pull updated AP beacon from mac80211. will fail if not in AP mode */
-       beacon = ieee80211_beacon_get(priv->hw, priv->interface_id, NULL);
+       beacon = ieee80211_beacon_get(priv->hw, priv->vif, NULL);
 
        if (!beacon) {
                IWL_ERROR("update beacon failed\n");
@@ -3657,6 +3661,7 @@ static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv,
                                        (priv->last_scan_jiffies, jiffies)));
 
        priv->last_scan_jiffies = jiffies;
+       priv->next_scan_jiffies = 0;
 }
 
 /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
@@ -3699,6 +3704,7 @@ static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv,
        }
 
        priv->last_scan_jiffies = jiffies;
+       priv->next_scan_jiffies = 0;
        IWL_DEBUG_INFO("Setting scan to off\n");
 
        clear_bit(STATUS_SCANNING, &priv->status);
@@ -3775,13 +3781,10 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv)
            iwl3945_rx_pm_debug_statistics_notif;
        priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif;
 
-       /* NOTE:  iwl3945_rx_statistics is different based on whether
-        * the build is for the 3945 or the 4965.  See the
-        * corresponding implementation in iwl-XXXX.c
-        *
-        * The same handler is used for both the REPLY to a
-        * discrete statistics request from the host as well as
-        * for the periodic statistics notification from the uCode
+       /*
+        * The same handler is used for both the REPLY to a discrete
+        * statistics request from the host as well as for the periodic
+        * statistics notifications (after received beacons) from the uCode.
         */
        priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics;
        priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
@@ -3795,7 +3798,7 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv)
        priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
        priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
 
-       /* Setup hardware specific Rx handlers */
+       /* Set up hardware specific Rx handlers */
        iwl3945_hw_rx_handler_setup(priv);
 }
 
@@ -3867,10 +3870,10 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
  * The queue is empty (no good data) if WRITE = READ - 1, and is full if
  * WRITE = READ.
  *
- * During initialization the host sets up the READ queue position to the first
+ * During initialization, the host sets up the READ queue position to the first
  * INDEX position, and WRITE to the last (READ - 1 wrapped)
  *
- * When the firmware places a packet in a buffer it will advance the READ index
+ * When the firmware places a packet in a buffer, it will advance the READ index
  * and fire the RX interrupt.  The driver can then query the READ index and
  * process as many packets as possible, moving the WRITE index forward as it
  * resets the Rx queue buffers with new memory.
@@ -3892,16 +3895,16 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
  *
  * Driver sequence:
  *
- * iwl3945_rx_queue_alloc()       Allocates rx_free
- * iwl3945_rx_replenish()         Replenishes rx_free list from rx_used, and calls
+ * iwl3945_rx_queue_alloc()   Allocates rx_free
+ * iwl3945_rx_replenish()     Replenishes rx_free list from rx_used, and calls
  *                            iwl3945_rx_queue_restock
- * iwl3945_rx_queue_restock()     Moves available buffers from rx_free into Rx
+ * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx
  *                            queue, updates firmware pointers, and updates
  *                            the WRITE index.  If insufficient rx_free buffers
  *                            are available, schedules iwl3945_rx_replenish
  *
  * -- enable interrupts --
- * ISR - iwl3945_rx()             Detach iwl3945_rx_mem_buffers from pool up to the
+ * ISR - iwl3945_rx()         Detach iwl3945_rx_mem_buffers from pool up to the
  *                            READ INDEX, detaching the SKB from the pool.
  *                            Moves the packet buffer from queue to rx_used.
  *                            Calls iwl3945_rx_queue_restock to refill any empty
@@ -3927,12 +3930,6 @@ static int iwl3945_rx_queue_space(const struct iwl3945_rx_queue *q)
 
 /**
  * iwl3945_rx_queue_update_write_ptr - Update the write pointer for the RX queue
- *
- * NOTE: This function has 3945 and 4965 specific code sections
- * but is declared in base due to the majority of the
- * implementation being the same (only a numeric constant is
- * different)
- *
  */
 int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_rx_queue *q)
 {
@@ -3945,6 +3942,7 @@ int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_
        if (q->need_update == 0)
                goto exit_unlock;
 
+       /* If power-saving is in use, make sure device is awake */
        if (test_bit(STATUS_POWER_PMI, &priv->status)) {
                reg = iwl3945_read32(priv, CSR_UCODE_DRV_GP1);
 
@@ -3958,10 +3956,14 @@ int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_
                if (rc)
                        goto exit_unlock;
 
+               /* Device expects a multiple of 8 */
                iwl3945_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
                                     q->write & ~0x7);
                iwl3945_release_nic_access(priv);
+
+       /* Else device is assumed to be awake */
        } else
+               /* Device expects a multiple of 8 */
                iwl3945_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
 
 
@@ -3973,9 +3975,7 @@ int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_
 }
 
 /**
- * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer pointer.
- *
- * NOTE: This function has 3945 and 4965 specific code paths in it.
+ * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
  */
 static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl3945_priv *priv,
                                          dma_addr_t dma_addr)
@@ -3986,9 +3986,9 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl3945_priv *priv,
 /**
  * iwl3945_rx_queue_restock - refill RX queue from pre-allocated pool
  *
- * If there are slots in the RX queue that  need to be restocked,
+ * If there are slots in the RX queue that need to be restocked,
  * and we have free pre-allocated buffers, fill the ranks as much
- * as we can pulling from rx_free.
+ * as we can, pulling from rx_free.
  *
  * This moves the 'write' index forward to catch up with 'processed', and
  * also updates the memory address in the firmware to reference the new
@@ -4005,9 +4005,12 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv)
        spin_lock_irqsave(&rxq->lock, flags);
        write = rxq->write & ~0x7;
        while ((iwl3945_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+               /* Get next free Rx buffer, remove from free list */
                element = rxq->rx_free.next;
                rxb = list_entry(element, struct iwl3945_rx_mem_buffer, list);
                list_del(element);
+
+               /* Point to Rx buffer via next RBD in circular buffer */
                rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->dma_addr);
                rxq->queue[rxq->write] = rxb;
                rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
@@ -4020,7 +4023,8 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv)
                queue_work(priv->workqueue, &priv->rx_replenish);
 
 
-       /* If we've added more space for the firmware to place data, tell it */
+       /* If we've added more space for the firmware to place data, tell it.
+        * Increment device's write pointer in multiples of 8. */
        if ((write != (rxq->write & ~0x7))
            || (abs(rxq->write - rxq->read) > 7)) {
                spin_lock_irqsave(&rxq->lock, flags);
@@ -4042,9 +4046,8 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv)
  * Also restock the Rx queue via iwl3945_rx_queue_restock.
  * This is called as a scheduled work item (except for during initialization)
  */
-void iwl3945_rx_replenish(void *data)
+static void iwl3945_rx_allocate(struct iwl3945_priv *priv)
 {
-       struct iwl3945_priv *priv = data;
        struct iwl3945_rx_queue *rxq = &priv->rxq;
        struct list_head *element;
        struct iwl3945_rx_mem_buffer *rxb;
@@ -4053,6 +4056,8 @@ void iwl3945_rx_replenish(void *data)
        while (!list_empty(&rxq->rx_used)) {
                element = rxq->rx_used.next;
                rxb = list_entry(element, struct iwl3945_rx_mem_buffer, list);
+
+               /* Alloc a new receive buffer */
                rxb->skb =
                    alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC);
                if (!rxb->skb) {
@@ -4064,8 +4069,19 @@ void iwl3945_rx_replenish(void *data)
                         * more buffers it will schedule replenish */
                        break;
                }
+
+               /* If radiotap head is required, reserve some headroom here.
+                * The physical head count is a variable rx_stats->phy_count.
+                * We reserve 4 bytes here. Plus these extra bytes, the
+                * headroom of the physical head should be enough for the
+                * radiotap head that iwl3945 supported. See iwl3945_rt.
+                */
+               skb_reserve(rxb->skb, 4);
+
                priv->alloc_rxb_skb++;
                list_del(element);
+
+               /* Get physical address of RB/SKB */
                rxb->dma_addr =
                    pci_map_single(priv->pci_dev, rxb->skb->data,
                                   IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
@@ -4073,6 +4089,26 @@ void iwl3945_rx_replenish(void *data)
                rxq->free_count++;
        }
        spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
+/*
+ * this should be called while priv->lock is locked
+ */
+static void __iwl3945_rx_replenish(void *data)
+{
+       struct iwl3945_priv *priv = data;
+
+       iwl3945_rx_allocate(priv);
+       iwl3945_rx_queue_restock(priv);
+}
+
+
+void iwl3945_rx_replenish(void *data)
+{
+       struct iwl3945_priv *priv = data;
+       unsigned long flags;
+
+       iwl3945_rx_allocate(priv);
 
        spin_lock_irqsave(&priv->lock, flags);
        iwl3945_rx_queue_restock(priv);
@@ -4080,7 +4116,7 @@ void iwl3945_rx_replenish(void *data)
 }
 
 /* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have it's SKB set to NULL
+ * If an SKB has been detached, the POOL needs to have its SKB set to NULL
  * This free routine walks the list of POOL entries and if SKB is set to
  * non NULL it is unmapped and freed
  */
@@ -4110,12 +4146,16 @@ int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv)
        spin_lock_init(&rxq->lock);
        INIT_LIST_HEAD(&rxq->rx_free);
        INIT_LIST_HEAD(&rxq->rx_used);
+
+       /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
        rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
        if (!rxq->bd)
                return -ENOMEM;
+
        /* Fill the rx_used queue with _all_ of the Rx buffers */
        for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
                list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+
        /* Set us so that we have processed and used all buffers, but have
         * not restocked the Rx queue with fresh buffers */
        rxq->read = rxq->write = 0;
@@ -4173,13 +4213,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 */
@@ -4232,7 +4272,7 @@ int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm)
 }
 
 /**
- * iwl3945_rx_handle - Main entry function for receiving responses from the uCode
+ * iwl3945_rx_handle - Main entry function for receiving responses from uCode
  *
  * Uses the priv->rx_handlers callback function array to invoke
  * the appropriate handlers, including command responses,
@@ -4246,10 +4286,16 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
        u32 r, i;
        int reclaim;
        unsigned long flags;
+       u8 fill_rx = 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). */
        r = iwl3945_hw_get_rx_read(priv);
        i = rxq->read;
 
+       if (iwl3945_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
+               fill_rx = 1;
        /* Rx interrupt, but nothing sent from uCode */
        if (i == r)
                IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
@@ -4257,7 +4303,7 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
        while (i != r) {
                rxb = rxq->queue[i];
 
-               /* If an RXB doesn't have a queue slot associated with it
+               /* If an RXB doesn't have a Rx queue slot associated with it,
                 * then a bug has been introduced in the queue refilling
                 * routines -- catch it here */
                BUG_ON(rxb == NULL);
@@ -4296,8 +4342,8 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
                }
 
                if (reclaim) {
-                       /* Invoke any callbacks, transfer the skb to caller,
-                        * and fire off the (possibly) blocking iwl3945_send_cmd()
+                       /* Invoke any callbacks, transfer the skb to caller, and
+                        * fire off the (possibly) blocking iwl3945_send_cmd()
                         * as we reclaim the driver command queue */
                        if (rxb && rxb->skb)
                                iwl3945_tx_cmd_complete(priv, rxb);
@@ -4320,6 +4366,16 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
                list_add_tail(&rxb->list, &priv->rxq.rx_used);
                spin_unlock_irqrestore(&rxq->lock, flags);
                i = (i + 1) & RX_QUEUE_MASK;
+               /* If there are a lot of unused frames,
+                * restock the Rx queue so ucode won't assert. */
+               if (fill_rx) {
+                       count++;
+                       if (count >= 8) {
+                               priv->rxq.read = i;
+                               __iwl3945_rx_replenish(priv);
+                               count = 0;
+                       }
+               }
        }
 
        /* Backtrack one entry */
@@ -4327,6 +4383,9 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
        iwl3945_rx_queue_restock(priv);
 }
 
+/**
+ * iwl3945_tx_queue_update_write_ptr - Send new write index to hardware
+ */
 static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv,
                                  struct iwl3945_tx_queue *txq)
 {
@@ -4494,7 +4553,7 @@ static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv)
 
 }
 
-#define EVENT_START_OFFSET  (4 * sizeof(u32))
+#define EVENT_START_OFFSET  (6 * sizeof(u32))
 
 /**
  * iwl3945_print_event_log - Dump error event log to syslog
@@ -4671,7 +4730,8 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
 
 #ifdef CONFIG_IWL3945_DEBUG
        if (iwl3945_debug_level & IWL_DL_ISR) {
-               inta_mask = iwl3945_read32(priv, CSR_INT_MASK); /* just for debug */
+               /* just for debug */
+               inta_mask = iwl3945_read32(priv, CSR_INT_MASK);
                IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
                              inta, inta_mask, inta_fh);
        }
@@ -4705,8 +4765,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)
@@ -4714,7 +4775,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) {
@@ -4850,8 +4911,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);
 
@@ -4901,11 +4965,11 @@ static const u8 iwl3945_eeprom_band_1[14] = {
 };
 
 /* 5.2 GHz bands */
-static const u8 iwl3945_eeprom_band_2[] = {
+static const u8 iwl3945_eeprom_band_2[] = {    /* 4915-5080MHz */
        183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
 };
 
-static const u8 iwl3945_eeprom_band_3[] = {    /* 5205-5320MHz */
+static const u8 iwl3945_eeprom_band_3[] = {    /* 5170-5320MHz */
        34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
 };
 
@@ -4929,7 +4993,7 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban
                *eeprom_ch_info = priv->eeprom.band_1_channels;
                *eeprom_ch_index = iwl3945_eeprom_band_1;
                break;
-       case 2:         /* 5.2GHz band */
+       case 2:         /* 4.9GHz band */
                *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_2);
                *eeprom_ch_info = priv->eeprom.band_2_channels;
                *eeprom_ch_index = iwl3945_eeprom_band_2;
@@ -4939,12 +5003,12 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban
                *eeprom_ch_info = priv->eeprom.band_3_channels;
                *eeprom_ch_index = iwl3945_eeprom_band_3;
                break;
-       case 4:         /* 5.2GHz band */
+       case 4:         /* 5.5GHz band */
                *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_4);
                *eeprom_ch_info = priv->eeprom.band_4_channels;
                *eeprom_ch_index = iwl3945_eeprom_band_4;
                break;
-       case 5:         /* 5.2GHz band */
+       case 5:         /* 5.7GHz band */
                *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_5);
                *eeprom_ch_info = priv->eeprom.band_5_channels;
                *eeprom_ch_index = iwl3945_eeprom_band_5;
@@ -4955,6 +5019,11 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban
        }
 }
 
+/**
+ * iwl3945_get_channel_info - Find driver's private channel info
+ *
+ * Based on band and channel number.
+ */
 const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv,
                                                    int phymode, u16 channel)
 {
@@ -4982,6 +5051,9 @@ const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945
 #define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
                            ? # x " " : "")
 
+/**
+ * iwl3945_init_channel_map - Set up driver's info for all possible channels
+ */
 static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
 {
        int eeprom_ch_count = 0;
@@ -5091,12 +5163,22 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
                }
        }
 
+       /* Set up txpower settings in driver for all channels */
        if (iwl3945_txpower_set_from_eeprom(priv))
                return -EIO;
 
        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.  */
@@ -5207,7 +5289,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
                scan_ch->active_dwell = cpu_to_le16(active_dwell);
                scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
 
-               /* Set power levels to defaults */
+               /* Set txpower levels to defaults */
                scan_ch->tpc.dsp_atten = 110;
                /* scan_pwr_info->tpc.dsp_atten; */
 
@@ -5217,8 +5299,8 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
                else {
                        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;
+                        * power level:
+                        * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
                         */
                }
 
@@ -5422,6 +5504,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
@@ -5430,48 +5523,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);
 }
 
 /**
@@ -5602,8 +5659,9 @@ static int iwl3945_verify_ucode(struct iwl3945_priv *priv)
 
        IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
 
-       /* Show first several data entries in instruction SRAM.
-        * Selection of bootstrap image is arbitrary. */
+       /* Since nothing seems to match, show first several data entries in
+        * instruction SRAM, so maybe visual inspection will give a clue.
+        * Selection of bootstrap image (vs. other images) is arbitrary. */
        image = (__le32 *)priv->ucode_boot.v_addr;
        len = priv->ucode_boot.len;
        rc = iwl3945_verify_inst_full(priv, image, len);
@@ -5695,7 +5753,7 @@ static int iwl3945_load_bsm(struct iwl3945_priv *priv)
                return -EINVAL;
 
        /* Tell bootstrap uCode where to find the "Initialize" uCode
-        *   in host DRAM ... bits 31:0 for 3945, bits 35:4 for 4965.
+        *   in host DRAM ... host DRAM physical address bits 31:0 for 3945.
         * NOTE:  iwl3945_initialize_alive_start() will replace these values,
         *        after the "initialize" uCode has run, to point to
         *        runtime/protocol instructions and backup data cache. */
@@ -5775,7 +5833,7 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv)
 static int iwl3945_read_ucode(struct iwl3945_priv *priv)
 {
        struct iwl3945_ucode *ucode;
-       int rc = 0;
+       int ret = 0;
        const struct firmware *ucode_raw;
        /* firmware file name contains uCode/driver compatibility version */
        const char *name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode";
@@ -5785,9 +5843,10 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
 
        /* Ask kernel firmware_class module to get the boot firmware off disk.
         * request_firmware() is synchronous, file is in memory on return. */
-       rc = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
-       if (rc < 0) {
-               IWL_ERROR("%s firmware file req failed: Reason %d\n", name, rc);
+       ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
+       if (ret < 0) {
+               IWL_ERROR("%s firmware file req failed: Reason %d\n",
+                               name, ret);
                goto error;
        }
 
@@ -5797,7 +5856,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
        /* Make sure that we got at least our header! */
        if (ucode_raw->size < sizeof(*ucode)) {
                IWL_ERROR("File size way too small!\n");
-               rc = -EINVAL;
+               ret = -EINVAL;
                goto err_release;
        }
 
@@ -5825,43 +5884,40 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
 
                IWL_DEBUG_INFO("uCode file size %d too small\n",
                               (int)ucode_raw->size);
-               rc = -EINVAL;
+               ret = -EINVAL;
                goto err_release;
        }
 
        /* Verify that uCode images will fit in card's SRAM */
        if (inst_size > IWL_MAX_INST_SIZE) {
-               IWL_DEBUG_INFO("uCode instr len %d too large to fit in card\n",
-                              (int)inst_size);
-               rc = -EINVAL;
+               IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n",
+                              inst_size);
+               ret = -EINVAL;
                goto err_release;
        }
 
        if (data_size > IWL_MAX_DATA_SIZE) {
-               IWL_DEBUG_INFO("uCode data len %d too large to fit in card\n",
-                              (int)data_size);
-               rc = -EINVAL;
+               IWL_DEBUG_INFO("uCode data len %d too large to fit in\n",
+                              data_size);
+               ret = -EINVAL;
                goto err_release;
        }
        if (init_size > IWL_MAX_INST_SIZE) {
-               IWL_DEBUG_INFO
-                   ("uCode init instr len %d too large to fit in card\n",
-                    (int)init_size);
-               rc = -EINVAL;
+               IWL_DEBUG_INFO("uCode init instr len %d too large to fit in\n",
+                               init_size);
+               ret = -EINVAL;
                goto err_release;
        }
        if (init_data_size > IWL_MAX_DATA_SIZE) {
-               IWL_DEBUG_INFO
-                   ("uCode init data len %d too large to fit in card\n",
-                    (int)init_data_size);
-               rc = -EINVAL;
+               IWL_DEBUG_INFO("uCode init data len %d too large to fit in\n",
+                               init_data_size);
+               ret = -EINVAL;
                goto err_release;
        }
        if (boot_size > IWL_MAX_BSM_SIZE) {
-               IWL_DEBUG_INFO
-                   ("uCode boot instr len %d too large to fit in bsm\n",
-                    (int)boot_size);
-               rc = -EINVAL;
+               IWL_DEBUG_INFO("uCode boot instr len %d too large to fit in\n",
+                               boot_size);
+               ret = -EINVAL;
                goto err_release;
        }
 
@@ -5871,56 +5927,45 @@ 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;
-       priv->ucode_code.v_addr =
-           pci_alloc_consistent(priv->pci_dev,
-                                priv->ucode_code.len,
-                                &(priv->ucode_code.p_addr));
+       iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
 
        priv->ucode_data.len = data_size;
-       priv->ucode_data.v_addr =
-           pci_alloc_consistent(priv->pci_dev,
-                                priv->ucode_data.len,
-                                &(priv->ucode_data.p_addr));
+       iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
 
        priv->ucode_data_backup.len = data_size;
-       priv->ucode_data_backup.v_addr =
-           pci_alloc_consistent(priv->pci_dev,
-                                priv->ucode_data_backup.len,
-                                &(priv->ucode_data_backup.p_addr));
+       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)
+               goto err_pci_alloc;
 
        /* Initialization instructions and data */
-       priv->ucode_init.len = init_size;
-       priv->ucode_init.v_addr =
-           pci_alloc_consistent(priv->pci_dev,
-                                priv->ucode_init.len,
-                                &(priv->ucode_init.p_addr));
-
-       priv->ucode_init_data.len = init_data_size;
-       priv->ucode_init_data.v_addr =
-           pci_alloc_consistent(priv->pci_dev,
-                                priv->ucode_init_data.len,
-                                &(priv->ucode_init_data.p_addr));
+       if (init_size && init_data_size) {
+               priv->ucode_init.len = init_size;
+               iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
+
+               priv->ucode_init_data.len = init_data_size;
+               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;
+       }
 
        /* Bootstrap (instructions only, no data) */
-       priv->ucode_boot.len = boot_size;
-       priv->ucode_boot.v_addr =
-           pci_alloc_consistent(priv->pci_dev,
-                                priv->ucode_boot.len,
-                                &(priv->ucode_boot.p_addr));
+       if (boot_size) {
+               priv->ucode_boot.len = boot_size;
+               iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
 
-       if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
-           !priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr ||
-           !priv->ucode_boot.v_addr || !priv->ucode_data_backup.v_addr)
-               goto err_pci_alloc;
+               if (!priv->ucode_boot.v_addr)
+                       goto err_pci_alloc;
+       }
 
        /* Copy images into buffers for card's bus-master reads ... */
 
        /* Runtime instructions (first block of data in file) */
        src = &ucode->data[0];
        len = priv->ucode_code.len;
-       IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %d\n",
-                      (int)len);
+       IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %Zd\n", len);
        memcpy(priv->ucode_code.v_addr, src, len);
        IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
                priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
@@ -5929,8 +5974,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
         * NOTE:  Copy into backup buffer will be done in iwl3945_up()  */
        src = &ucode->data[inst_size];
        len = priv->ucode_data.len;
-       IWL_DEBUG_INFO("Copying (but not loading) uCode data len %d\n",
-                      (int)len);
+       IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len);
        memcpy(priv->ucode_data.v_addr, src, len);
        memcpy(priv->ucode_data_backup.v_addr, src, len);
 
@@ -5938,8 +5982,8 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
        if (init_size) {
                src = &ucode->data[inst_size + data_size];
                len = priv->ucode_init.len;
-               IWL_DEBUG_INFO("Copying (but not loading) init instr len %d\n",
-                              (int)len);
+               IWL_DEBUG_INFO("Copying (but not loading) init instr len %Zd\n",
+                              len);
                memcpy(priv->ucode_init.v_addr, src, len);
        }
 
@@ -5965,14 +6009,14 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
 
  err_pci_alloc:
        IWL_ERROR("failed to allocate pci memory\n");
-       rc = -ENOMEM;
+       ret = -ENOMEM;
        iwl3945_dealloc_ucode_pci(priv);
 
  err_release:
        release_firmware(ucode_raw);
 
  error:
-       return rc;
+       return ret;
 }
 
 
@@ -6028,12 +6072,8 @@ static int iwl3945_set_ucode_ptrs(struct iwl3945_priv *priv)
  *
  * Called after REPLY_ALIVE notification received from "initialize" uCode.
  *
- * The 4965 "initialize" ALIVE reply contains calibration data for:
- *   Voltage, temperature, and MIMO tx gain correction, now stored in priv
- *   (3945 does not contain this data).
- *
  * Tell "initialize" uCode to go ahead and load the runtime uCode.
-*/
+ */
 static void iwl3945_init_alive_start(struct iwl3945_priv *priv)
 {
        /* Check alive response for "valid" sign from uCode */
@@ -6128,44 +6168,16 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
        } else
                set_bit(STATUS_RF_KILL_HW, &priv->status);
 
-       /* After the ALIVE response, we can process host commands */
+       /* After the ALIVE response, we can send commands to 3945 uCode */
        set_bit(STATUS_ALIVE, &priv->status);
 
        /* 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);
-
        if (iwl3945_is_rfkill(priv))
                return;
 
-       if (!priv->mac80211_registered) {
-               /* Unlock so any user space entry points can call back into
-                * the driver without a deadlock... */
-               mutex_unlock(&priv->mutex);
-               iwl3945_rate_control_register(priv->hw);
-               rc = ieee80211_register_hw(priv->hw);
-               priv->hw->conf.beacon_int = 100;
-               mutex_lock(&priv->mutex);
-
-               if (rc) {
-                       iwl3945_rate_control_unregister(priv->hw);
-                       IWL_ERROR("Failed to register network "
-                                 "device (error %d)\n", rc);
-                       return;
-               }
-
-               priv->mac80211_registered = 1;
-
-               iwl3945_reset_channel_flag(priv);
-       } else
-               ieee80211_start_queues(priv->hw);
+       ieee80211_start_queues(priv->hw);
 
        priv->active_rate = priv->rates_mask;
        priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
@@ -6185,7 +6197,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
                memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
        }
 
-       /* Configure BT coexistence */
+       /* Configure Bluetooth device coexistence support */
        iwl3945_send_bt_config(priv);
 
        /* Configure the adapter for unassociated operation */
@@ -6198,6 +6210,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
        iwl3945_reg_txpower_periodic(priv);
 
        IWL_DEBUG_INFO("ALIVE processing complete.\n");
+       wake_up_interruptible(&priv->wait_command_queue);
 
        if (priv->error_recovering)
                iwl3945_error_recovery(priv);
@@ -6249,6 +6262,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;
@@ -6260,6 +6275,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) <<
@@ -6310,7 +6327,6 @@ static void iwl3945_down(struct iwl3945_priv *priv)
 
 static int __iwl3945_up(struct iwl3945_priv *priv)
 {
-       DECLARE_MAC_BUF(mac);
        int rc, i;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
@@ -6321,7 +6337,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) {
@@ -6329,6 +6345,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);
@@ -6354,7 +6382,11 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
         * This will be used to initialize the on-board processor's
         * data SRAM for a clean start when the runtime program first loads. */
        memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
-                       priv->ucode_data.len);
+              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++) {
 
@@ -6373,13 +6405,6 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
                /* start card; "initialize" will load runtime ucode */
                iwl3945_nic_start(priv);
 
-               /* MAC Address location in EEPROM same for 3945/4965 */
-               get_eeprom_mac(priv, priv->mac_addr);
-               IWL_DEBUG_INFO("MAC address: %s\n",
-                              print_mac(mac, priv->mac_addr));
-
-               SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
-
                IWL_DEBUG_INFO(DRV_NAME " is coming up\n");
 
                return 0;
@@ -6613,7 +6638,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;
@@ -6716,6 +6741,8 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
        mutex_unlock(&priv->mutex);
 }
 
+#define IWL_DELAY_NEXT_SCAN (HZ*2)
+
 static void iwl3945_bg_post_associate(struct work_struct *data)
 {
        struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv,
@@ -6740,7 +6767,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
 
        mutex_lock(&priv->mutex);
 
-       if (!priv->interface_id || !priv->is_open) {
+       if (!priv->vif || !priv->is_open) {
                mutex_unlock(&priv->mutex);
                return;
        }
@@ -6816,6 +6843,8 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
 #ifdef CONFIG_IWL3945_QOS
        iwl3945_activate_qos(priv, 0);
 #endif /* CONFIG_IWL3945_QOS */
+       /* we have just associated, don't start scan too early */
+       priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
        mutex_unlock(&priv->mutex);
 }
 
@@ -6834,6 +6863,8 @@ static void iwl3945_bg_abort_scan(struct work_struct *work)
        mutex_unlock(&priv->mutex);
 }
 
+static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+
 static void iwl3945_bg_scan_completed(struct work_struct *work)
 {
        struct iwl3945_priv *priv =
@@ -6844,6 +6875,9 @@ static void iwl3945_bg_scan_completed(struct work_struct *work)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
+       if (test_bit(STATUS_CONF_PENDING, &priv->status))
+               iwl3945_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw));
+
        ieee80211_scan_completed(priv->hw);
 
        /* Since setting the TXPOWER may have been deferred while
@@ -6859,23 +6893,83 @@ static void iwl3945_bg_scan_completed(struct work_struct *work)
  *
  *****************************************************************************/
 
+#define UCODE_READY_TIMEOUT    (2 * HZ)
+
 static int iwl3945_mac_start(struct ieee80211_hw *hw)
 {
        struct iwl3945_priv *priv = hw->priv;
+       int ret;
 
        IWL_DEBUG_MAC80211("enter\n");
 
+       if (pci_enable_device(priv->pci_dev)) {
+               IWL_ERROR("Fail to pci_enable_device\n");
+               return -ENODEV;
+       }
+       pci_restore_state(priv->pci_dev);
+       pci_enable_msi(priv->pci_dev);
+
+       ret = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED,
+                         DRV_NAME, priv);
+       if (ret) {
+               IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq);
+               goto out_disable_msi;
+       }
+
        /* we should be verifying the device is ready to be opened */
        mutex_lock(&priv->mutex);
 
-       priv->is_open = 1;
+       memset(&priv->staging_rxon, 0, sizeof(struct iwl3945_rxon_cmd));
+       /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
+        * ucode filename and max sizes are card-specific. */
 
-       if (!iwl3945_is_rfkill(priv))
-               ieee80211_start_queues(priv->hw);
+       if (!priv->ucode_code.len) {
+               ret = iwl3945_read_ucode(priv);
+               if (ret) {
+                       IWL_ERROR("Could not read microcode: %d\n", ret);
+                       mutex_unlock(&priv->mutex);
+                       goto out_release_irq;
+               }
+       }
+
+       ret = __iwl3945_up(priv);
 
        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,
+                       test_bit(STATUS_READY, &priv->status),
+                       UCODE_READY_TIMEOUT);
+       if (!ret) {
+               if (!test_bit(STATUS_READY, &priv->status)) {
+                       IWL_ERROR("Wait for START_ALIVE timeout after %dms.\n",
+                                 jiffies_to_msecs(UCODE_READY_TIMEOUT));
+                       ret = -ETIMEDOUT;
+                       goto out_release_irq;
+               }
+       }
+
+       priv->is_open = 1;
        IWL_DEBUG_MAC80211("leave\n");
        return 0;
+
+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;
 }
 
 static void iwl3945_mac_stop(struct ieee80211_hw *hw)
@@ -6884,17 +6978,30 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
 
        IWL_DEBUG_MAC80211("enter\n");
 
+       if (!priv->is_open) {
+               IWL_DEBUG_MAC80211("leave - skip\n");
+               return;
+       }
 
-       mutex_lock(&priv->mutex);
-       /* stop mac, cancel any scan request and clear
-        * RXON_FILTER_ASSOC_MSK BIT
-        */
        priv->is_open = 0;
-       iwl3945_scan_cancel_timeout(priv, 100);
-       cancel_delayed_work(&priv->post_associate);
-       priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       iwl3945_commit_rxon(priv);
-       mutex_unlock(&priv->mutex);
+
+       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);
+               mutex_unlock(&priv->mutex);
+       }
+
+       iwl3945_down(priv);
+
+       flush_workqueue(priv->workqueue);
+       free_irq(priv->pci_dev->irq, priv);
+       pci_disable_msi(priv->pci_dev);
+       pci_save_state(priv->pci_dev);
+       pci_disable_device(priv->pci_dev);
 
        IWL_DEBUG_MAC80211("leave\n");
 }
@@ -6928,15 +7035,15 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
        unsigned long flags;
        DECLARE_MAC_BUF(mac);
 
-       IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type);
+       IWL_DEBUG_MAC80211("enter: type %d\n", conf->type);
 
-       if (priv->interface_id) {
-               IWL_DEBUG_MAC80211("leave - interface_id != 0\n");
+       if (priv->vif) {
+               IWL_DEBUG_MAC80211("leave - vif != NULL\n");
                return -EOPNOTSUPP;
        }
 
        spin_lock_irqsave(&priv->lock, flags);
-       priv->interface_id = conf->if_id;
+       priv->vif = conf->vif;
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -6947,11 +7054,12 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
                memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
        }
 
-       iwl3945_set_mode(priv, conf->type);
+       if (iwl3945_is_ready(priv))
+               iwl3945_set_mode(priv, conf->type);
 
-       IWL_DEBUG_MAC80211("leave\n");
        mutex_unlock(&priv->mutex);
 
+       IWL_DEBUG_MAC80211("leave\n");
        return 0;
 }
 
@@ -6967,21 +7075,23 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
        struct iwl3945_priv *priv = hw->priv;
        const struct iwl3945_channel_info *ch_info;
        unsigned long flags;
+       int ret = 0;
 
        mutex_lock(&priv->mutex);
        IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
 
+       priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+
        if (!iwl3945_is_ready(priv)) {
                IWL_DEBUG_MAC80211("leave - not ready\n");
-               mutex_unlock(&priv->mutex);
-               return -EIO;
+               ret = -EIO;
+               goto out;
        }
 
-       /* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only
-        * what is exposed through include/ declarations */
        if (unlikely(!iwl3945_param_disable_hw_scan &&
                     test_bit(STATUS_SCANNING, &priv->status))) {
                IWL_DEBUG_MAC80211("leave - scanning\n");
+               set_bit(STATUS_CONF_PENDING, &priv->status);
                mutex_unlock(&priv->mutex);
                return 0;
        }
@@ -6994,8 +7104,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
                               conf->channel, conf->phymode);
                IWL_DEBUG_MAC80211("leave - invalid channel\n");
                spin_unlock_irqrestore(&priv->lock, flags);
-               mutex_unlock(&priv->mutex);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel);
@@ -7012,8 +7122,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
 #ifdef IEEE80211_CONF_CHANNEL_SWITCH
        if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
                iwl3945_hw_channel_switch(priv, conf->channel);
-               mutex_unlock(&priv->mutex);
-               return 0;
+               goto out;
        }
 #endif
 
@@ -7021,14 +7130,13 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
 
        if (!conf->radio_enabled) {
                IWL_DEBUG_MAC80211("leave - radio disabled\n");
-               mutex_unlock(&priv->mutex);
-               return 0;
+               goto out;
        }
 
        if (iwl3945_is_rfkill(priv)) {
                IWL_DEBUG_MAC80211("leave - RF kill\n");
-               mutex_unlock(&priv->mutex);
-               return -EIO;
+               ret = -EIO;
+               goto out;
        }
 
        iwl3945_set_rate(priv);
@@ -7041,16 +7149,17 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
 
        IWL_DEBUG_MAC80211("leave\n");
 
+out:
+       clear_bit(STATUS_CONF_PENDING, &priv->status);
        mutex_unlock(&priv->mutex);
-
-       return 0;
+       return ret;
 }
 
 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 */
@@ -7103,7 +7212,8 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
         * clear sta table, add BCAST sta... */
 }
 
-static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, int if_id,
+static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
+                                       struct ieee80211_vif *vif,
                                    struct ieee80211_if_conf *conf)
 {
        struct iwl3945_priv *priv = hw->priv;
@@ -7123,9 +7233,11 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, int if_id,
                return 0;
        }
 
+       if (!iwl3945_is_alive(priv))
+               return -EAGAIN;
+
        mutex_lock(&priv->mutex);
 
-       IWL_DEBUG_MAC80211("enter: interface id %d\n", if_id);
        if (conf->bssid)
                IWL_DEBUG_MAC80211("bssid: %s\n",
                                   print_mac(mac, conf->bssid));
@@ -7142,8 +7254,8 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, int if_id,
                return 0;
        }
 
-       if (priv->interface_id != if_id) {
-               IWL_DEBUG_MAC80211("leave - interface_id != if_id\n");
+       if (priv->vif != vif) {
+               IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
                mutex_unlock(&priv->mutex);
                return 0;
        }
@@ -7161,6 +7273,9 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, int if_id,
                priv->ibss_beacon = conf->beacon;
        }
 
+       if (iwl3945_is_rfkill(priv))
+               goto done;
+
        if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
            !is_multicast_ether_addr(conf->bssid)) {
                /* If there is currently a HW scan going on in the background
@@ -7195,6 +7310,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, int if_id,
                iwl3945_commit_rxon(priv);
        }
 
+ done:
        spin_lock_irqsave(&priv->lock, flags);
        if (!conf->ssid_len)
                memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
@@ -7231,13 +7347,14 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
 
        mutex_lock(&priv->mutex);
 
-       iwl3945_scan_cancel_timeout(priv, 100);
-       cancel_delayed_work(&priv->post_associate);
-       priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       iwl3945_commit_rxon(priv);
-
-       if (priv->interface_id == conf->if_id) {
-               priv->interface_id = 0;
+       if (iwl3945_is_ready_rf(priv)) {
+               iwl3945_scan_cancel_timeout(priv, 100);
+               cancel_delayed_work(&priv->post_associate);
+               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+               iwl3945_commit_rxon(priv);
+       }
+       if (priv->vif == conf->vif) {
+               priv->vif = NULL;
                memset(priv->bssid, 0, ETH_ALEN);
                memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
                priv->essid_len = 0;
@@ -7245,10 +7362,8 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
        mutex_unlock(&priv->mutex);
 
        IWL_DEBUG_MAC80211("leave\n");
-
 }
 
-#define IWL_DELAY_NEXT_SCAN (HZ*2)
 static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
 {
        int rc = 0;
@@ -7272,16 +7387,20 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
                goto out_unlock;
        }
 
+       /* we don't schedule scan within next_scan_jiffies period */
+       if (priv->next_scan_jiffies &&
+                       time_after(priv->next_scan_jiffies, jiffies)) {
+               rc = -EAGAIN;
+               goto out_unlock;
+       }
        /* if we just finished scan ask for delay */
-       if (priv->last_scan_jiffies &&
-           time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
-                      jiffies)) {
+       if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies +
+                               IWL_DELAY_NEXT_SCAN, jiffies)) {
                rc = -EAGAIN;
                goto out_unlock;
        }
        if (len) {
-               IWL_DEBUG_SCAN("direct scan for  "
-                              "%s [%d]\n ",
+               IWL_DEBUG_SCAN("direct scan for %s [%d]\n ",
                               iwl3945_escape_essid(ssid, len), (int)len);
 
                priv->one_direct_scan = 1;
@@ -7370,7 +7489,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
 #ifdef CONFIG_IWL3945_QOS
        unsigned long flags;
        int q;
-#endif /* CONFIG_IWL_QOS */
+#endif /* CONFIG_IWL3945_QOS */
 
        IWL_DEBUG_MAC80211("enter\n");
 
@@ -7503,6 +7622,12 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
+       if (!iwl3945_is_ready_rf(priv)) {
+               IWL_DEBUG_MAC80211("leave - not ready\n");
+               mutex_unlock(&priv->mutex);
+               return;
+       }
+
        /* we are restarting association process
         * clear RXON_FILTER_ASSOC_MSK bit
        */
@@ -7520,12 +7645,6 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
                return;
        }
 
-       if (!iwl3945_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211("leave - not ready\n");
-               mutex_unlock(&priv->mutex);
-               return;
-       }
-
        priv->only_active_channel = 0;
 
        iwl3945_set_rate(priv);
@@ -8328,7 +8447,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        struct iwl3945_priv *priv;
        struct ieee80211_hw *hw;
        int i;
+       DECLARE_MAC_BUF(mac);
 
+       /* Disabling hardware scan means that mac80211 will perform scans
+        * "the hard way", rather than using device's scan. */
        if (iwl3945_param_disable_hw_scan) {
                IWL_DEBUG_INFO("Disabling hw_scan\n");
                iwl3945_hw_ops.hw_scan = NULL;
@@ -8359,6 +8481,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        priv->hw = hw;
 
        priv->pci_dev = pdev;
+
+       /* Select antenna (may be helpful if only one antenna is connected) */
        priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna;
 #ifdef CONFIG_IWL3945_DEBUG
        iwl3945_debug_level = iwl3945_param_debug;
@@ -8380,6 +8504,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        /* Tell mac80211 our Tx characteristics */
        hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
 
+       /* 4 EDCA QOS priorities */
        hw->queues = 4;
 
        spin_lock_init(&priv->lock);
@@ -8400,6 +8525,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        pci_set_master(pdev);
 
+       /* Clear the driver's (not device's) station table */
        iwl3945_clear_stations_table(priv);
 
        priv->data_retry_limit = -1;
@@ -8419,9 +8545,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        err = pci_request_regions(pdev, DRV_NAME);
        if (err)
                goto out_pci_disable_device;
+
        /* We disable the RETRY_TIMEOUT register (0x41) to keep
         * PCI Tx retries from interfering with C3 CPU state */
        pci_write_config_byte(pdev, 0x41, 0x00);
+
        priv->hw_base = pci_iomap(pdev, 0, 0);
        if (!priv->hw_base) {
                err = -ENODEV;
@@ -8434,6 +8562,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        /* Initialize module parameter values here */
 
+       /* Disable radio (SW RF KILL) via parameter when loading driver */
        if (iwl3945_param_disable) {
                set_bit(STATUS_RF_KILL_SW, &priv->status);
                IWL_DEBUG_INFO("Radio disabled.\n");
@@ -8471,7 +8600,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        /* Device-specific setup */
        if (iwl3945_hw_set_hw_setting(priv)) {
                IWL_ERROR("failed to set hw settings\n");
-               mutex_unlock(&priv->mutex);
                goto out_iounmap;
        }
 
@@ -8496,50 +8624,70 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        iwl3945_disable_interrupts(priv);
 
-       pci_enable_msi(pdev);
-
-       err = request_irq(pdev->irq, iwl3945_isr, IRQF_SHARED, DRV_NAME, priv);
-       if (err) {
-               IWL_ERROR("Error allocating IRQ %d\n", pdev->irq);
-               goto out_disable_msi;
-       }
-
-       mutex_lock(&priv->mutex);
-
        err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
        if (err) {
                IWL_ERROR("failed to create sysfs device attributes\n");
-               mutex_unlock(&priv->mutex);
                goto out_release_irq;
        }
 
-       /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
-        * ucode filename and max sizes are card-specific. */
-       err = iwl3945_read_ucode(priv);
+       /* nic init */
+       iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+                    CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+
+        iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+        err = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
+                          CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+                          CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+        if (err < 0) {
+                IWL_DEBUG_INFO("Failed to init the card\n");
+               goto out_remove_sysfs;
+        }
+       /* Read the EEPROM */
+       err = iwl3945_eeprom_init(priv);
        if (err) {
-               IWL_ERROR("Could not read microcode: %d\n", err);
-               mutex_unlock(&priv->mutex);
-               goto out_pci_alloc;
+               IWL_ERROR("Unable to init EEPROM\n");
+               goto out_remove_sysfs;
        }
+       /* MAC Address location in EEPROM same for 3945/4965 */
+       get_eeprom_mac(priv, priv->mac_addr);
+       IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
+       SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 
-       mutex_unlock(&priv->mutex);
+       err = iwl3945_init_channel_map(priv);
+       if (err) {
+               IWL_ERROR("initializing regulatory failed: %d\n", err);
+               goto out_remove_sysfs;
+       }
 
-       IWL_DEBUG_INFO("Queueing UP work.\n");
+       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);
 
-       queue_work(priv->workqueue, &priv->up);
+       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_free_geos;
+       }
 
-       return 0;
+       priv->hw->conf.beacon_int = 100;
+       priv->mac80211_registered = 1;
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
 
- out_pci_alloc:
-       iwl3945_dealloc_ucode_pci(priv);
+       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);
 
  out_release_irq:
-       free_irq(pdev->irq, priv);
-
- out_disable_msi:
-       pci_disable_msi(pdev);
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
        iwl3945_unset_hw_setting(priv);
@@ -8605,17 +8753,13 @@ static void iwl3945_pci_remove(struct pci_dev *pdev)
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
 
-       free_irq(pdev->irq, priv);
-       pci_disable_msi(pdev);
        pci_iounmap(pdev, priv->hw_base);
        pci_release_regions(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);
@@ -8629,89 +8773,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;
 }