headers: remove sched.h from interrupt.h
[safe/jmp/linux-2.6] / drivers / net / wireless / iwlwifi / iwl3945-base.c
index 16ecf03..aa49230 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
@@ -89,194 +90,12 @@ MODULE_LICENSE("GPL");
 
  /* module parameters */
 struct iwl_mod_params iwl3945_mod_params = {
-       .num_of_queues = IWL39_MAX_NUM_QUEUES,
+       .num_of_queues = IWL39_NUM_QUEUES, /* Not used */
        .sw_crypto = 1,
        .restart_fw = 1,
        /* the rest are 0 by default */
 };
 
-/*************** STATION TABLE MANAGEMENT ****
- * 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 iwl_priv *priv, const u8 *addr, int is_ap)
-{
-       int index = IWL_INVALID_STATION;
-       int i;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-
-       if (is_ap)
-               index = IWL_AP_ID;
-       else if (is_broadcast_ether_addr(addr))
-               index = priv->hw_params.bcast_sta_id;
-       else
-               for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
-                       if (priv->stations_39[i].used &&
-                           !compare_ether_addr(priv->stations_39[i].sta.sta.addr,
-                                               addr)) {
-                               index = i;
-                               break;
-                       }
-
-       if (unlikely(index == IWL_INVALID_STATION))
-               goto out;
-
-       if (priv->stations_39[index].used) {
-               priv->stations_39[index].used = 0;
-               priv->num_stations--;
-       }
-
-       BUG_ON(priv->num_stations < 0);
-
-out:
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-       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 iwl_priv *priv)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-
-       priv->num_stations = 0;
-       memset(priv->stations_39, 0, sizeof(priv->stations_39));
-
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-
-/**
- * iwl3945_add_station - Add station to station tables in driver and device
- */
-u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags)
-{
-       int i;
-       int index = IWL_INVALID_STATION;
-       struct iwl3945_station_entry *station;
-       unsigned long flags_spin;
-       u8 rate;
-
-       spin_lock_irqsave(&priv->sta_lock, flags_spin);
-       if (is_ap)
-               index = IWL_AP_ID;
-       else if (is_broadcast_ether_addr(addr))
-               index = priv->hw_params.bcast_sta_id;
-       else
-               for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
-                       if (!compare_ether_addr(priv->stations_39[i].sta.sta.addr,
-                                               addr)) {
-                               index = i;
-                               break;
-                       }
-
-                       if (!priv->stations_39[i].used &&
-                           index == IWL_INVALID_STATION)
-                               index = i;
-               }
-
-       /* These two conditions has the same outcome but keep them separate
-         since they have different meaning */
-       if (unlikely(index == IWL_INVALID_STATION)) {
-               spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-               return index;
-       }
-
-       if (priv->stations_39[index].used &&
-          !compare_ether_addr(priv->stations_39[index].sta.sta.addr, addr)) {
-               spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-               return index;
-       }
-
-       IWL_DEBUG_ASSOC(priv, "Add STA ID %d: %pM\n", index, addr);
-       station = &priv->stations_39[index];
-       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;
-       station->sta.sta.sta_id = index;
-       station->sta.station_flags = 0;
-
-       if (priv->band == IEEE80211_BAND_5GHZ)
-               rate = IWL_RATE_6M_PLCP;
-       else
-               rate =  IWL_RATE_1M_PLCP;
-
-       /* Turn on both antennas for the station... */
-       station->sta.rate_n_flags =
-                       iwl3945_hw_set_rate_n_flags(rate, RATE_MCS_ANT_AB_MSK);
-
-       spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-
-       /* Add station to device's station table */
-       iwl_send_add_sta(priv,
-                        (struct iwl_addsta_cmd *)&station->sta, flags);
-       return index;
-
-}
-
-static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
-{
-       int rc = 0;
-       struct iwl_rx_packet *res = NULL;
-       struct iwl3945_rxon_assoc_cmd rxon_assoc;
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_RXON_ASSOC,
-               .len = sizeof(rxon_assoc),
-               .meta.flags = CMD_WANT_SKB,
-               .data = &rxon_assoc,
-       };
-       const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
-       const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
-
-       if ((rxon1->flags == rxon2->flags) &&
-           (rxon1->filter_flags == rxon2->filter_flags) &&
-           (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
-           (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
-               IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
-               return 0;
-       }
-
-       rxon_assoc.flags = priv->staging_rxon.flags;
-       rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
-       rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
-       rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
-       rxon_assoc.reserved = 0;
-
-       rc = iwl_send_cmd_sync(priv, &cmd);
-       if (rc)
-               return rc;
-
-       res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
-       if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
-               rc = -EIO;
-       }
-
-       priv->alloc_rxb_skb--;
-       dev_kfree_skb_any(cmd.meta.u.skb);
-
-       return rc;
-}
-
 /**
  * iwl3945_get_antenna_flags - Get antenna flags for RXON command
  * @priv: eeprom and antenna fields are used to determine antenna flags
@@ -314,150 +133,6 @@ __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
        return 0;               /* "diversity" is default if error */
 }
 
-/**
- * iwl3945_commit_rxon - commit staging_rxon to hardware
- *
- * The RXON command in staging_rxon is committed to the hardware and
- * the active_rxon structure is updated with the new data.  This
- * function correctly transitions out of the RXON_ASSOC_MSK state if
- * a HW tune is required based on the RXON structure changes.
- */
-static int iwl3945_commit_rxon(struct iwl_priv *priv)
-{
-       /* cast away the const for active_rxon in this function */
-       struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
-       struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon;
-       int rc = 0;
-       bool new_assoc =
-               !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
-
-       if (!iwl_is_alive(priv))
-               return -1;
-
-       /* always get timestamp with Rx frame */
-       staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK;
-
-       /* select antenna */
-       staging_rxon->flags &=
-           ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
-       staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
-
-       rc = iwl_check_rxon_cmd(priv);
-       if (rc) {
-               IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
-               return -EINVAL;
-       }
-
-       /* If we don't need to send a full RXON, we can use
-        * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
-        * and other flags for the current radio configuration. */
-       if (!iwl_full_rxon_required(priv)) {
-               rc = iwl3945_send_rxon_assoc(priv);
-               if (rc) {
-                       IWL_ERR(priv, "Error setting RXON_ASSOC "
-                                 "configuration (%d).\n", rc);
-                       return rc;
-               }
-
-               memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
-
-               return 0;
-       }
-
-       /* If we are currently associated and the new config requires
-        * an RXON_ASSOC and the new config wants the associated mask enabled,
-        * we must clear the associated from the active configuration
-        * before we apply the new config */
-       if (iwl_is_associated(priv) && new_assoc) {
-               IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
-               active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-               /*
-                * reserved4 and 5 could have been filled by the iwlcore code.
-                * Let's clear them before pushing to the 3945.
-                */
-               active_rxon->reserved4 = 0;
-               active_rxon->reserved5 = 0;
-               rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
-                                     sizeof(struct iwl3945_rxon_cmd),
-                                     &priv->active_rxon);
-
-               /* If the mask clearing failed then we set
-                * active_rxon back to what it was previously */
-               if (rc) {
-                       active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-                       IWL_ERR(priv, "Error clearing ASSOC_MSK on current "
-                                 "configuration (%d).\n", rc);
-                       return rc;
-               }
-       }
-
-       IWL_DEBUG_INFO(priv, "Sending RXON\n"
-                      "* with%s RXON_FILTER_ASSOC_MSK\n"
-                      "* channel = %d\n"
-                      "* bssid = %pM\n",
-                      (new_assoc ? "" : "out"),
-                      le16_to_cpu(staging_rxon->channel),
-                      staging_rxon->bssid_addr);
-
-       /*
-        * reserved4 and 5 could have been filled by the iwlcore code.
-        * Let's clear them before pushing to the 3945.
-        */
-       staging_rxon->reserved4 = 0;
-       staging_rxon->reserved5 = 0;
-
-       iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
-
-       /* Apply the new configuration */
-       rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
-                             sizeof(struct iwl3945_rxon_cmd),
-                             staging_rxon);
-       if (rc) {
-               IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
-               return rc;
-       }
-
-       memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
-
-       iwl3945_clear_stations_table(priv);
-
-       /* If we issue a new RXON command which required a tune then we must
-        * send a new TXPOWER command or we won't be able to Tx any frames */
-       rc = priv->cfg->ops->lib->send_tx_power(priv);
-       if (rc) {
-               IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
-               return rc;
-       }
-
-       /* Add the broadcast address so we can send broadcast frames */
-       if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) ==
-           IWL_INVALID_STATION) {
-               IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
-               return -EIO;
-       }
-
-       /* If we have set the ASSOC_MSK and we are in BSS mode then
-        * add the IWL_AP_ID to the station rate table */
-       if (iwl_is_associated(priv) &&
-           (priv->iw_mode == NL80211_IFTYPE_STATION))
-               if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr,
-                                       1, 0)
-                   == IWL_INVALID_STATION) {
-                       IWL_ERR(priv, "Error adding AP address for transmit\n");
-                       return -EIO;
-               }
-
-       /* Init the hardware's rate fallback order based on the band */
-       rc = iwl3945_init_hw_rate_table(priv);
-       if (rc) {
-               IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc);
-               return -EIO;
-       }
-
-       return 0;
-}
-
 static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
                                   struct ieee80211_key_conf *keyconf,
                                   u8 sta_id)
@@ -477,12 +152,12 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
        key_flags &= ~STA_KEY_FLG_INVALID;
 
        spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations_39[sta_id].keyinfo.alg = keyconf->alg;
-       priv->stations_39[sta_id].keyinfo.keylen = keyconf->keylen;
-       memcpy(priv->stations_39[sta_id].keyinfo.key, keyconf->key,
+       priv->stations[sta_id].keyinfo.alg = keyconf->alg;
+       priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+       memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
               keyconf->keylen);
 
-       memcpy(priv->stations_39[sta_id].sta.key.key, keyconf->key,
+       memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
               keyconf->keylen);
 
        if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
@@ -495,14 +170,13 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
        WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
                "no space for a new key");
 
-       priv->stations_39[sta_id].sta.key.key_flags = key_flags;
-       priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-       priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+       priv->stations[sta_id].sta.key.key_flags = key_flags;
+       priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
        IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n");
 
-       ret = iwl_send_add_sta(priv,
-               (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, CMD_ASYNC);
+       ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
 
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
@@ -528,17 +202,16 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
        unsigned long flags;
 
        spin_lock_irqsave(&priv->sta_lock, flags);
-       memset(&priv->stations_39[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key));
-       memset(&priv->stations_39[sta_id].sta.key, 0,
+       memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
+       memset(&priv->stations[sta_id].sta.key, 0,
                sizeof(struct iwl4965_keyinfo));
-       priv->stations_39[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
-       priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-       priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+       priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
+       priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
        IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
-       iwl_send_add_sta(priv,
-               (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0);
+       iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0);
        return 0;
 }
 
@@ -560,7 +233,7 @@ static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
                ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id);
                break;
        default:
-               IWL_ERR(priv,"Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
+               IWL_ERR(priv, "Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
                ret = -EINVAL;
        }
 
@@ -689,120 +362,14 @@ static void iwl3945_unset_hw_params(struct iwl_priv *priv)
                                    priv->shared_phys);
 }
 
-#define MAX_UCODE_BEACON_INTERVAL      1024
-#define INTEL_CONN_LISTEN_INTERVAL     cpu_to_le16(0xA)
-
-static __le16 iwl3945_adjust_beacon_interval(u16 beacon_val)
-{
-       u16 new_val = 0;
-       u16 beacon_factor = 0;
-
-       beacon_factor =
-           (beacon_val + MAX_UCODE_BEACON_INTERVAL)
-               / MAX_UCODE_BEACON_INTERVAL;
-       new_val = beacon_val / beacon_factor;
-
-       return cpu_to_le16(new_val);
-}
-
-static void iwl3945_setup_rxon_timing(struct iwl_priv *priv)
-{
-       u64 interval_tm_unit;
-       u64 tsf, result;
-       unsigned long flags;
-       struct ieee80211_conf *conf = NULL;
-       u16 beacon_int = 0;
-
-       conf = ieee80211_get_hw_conf(priv->hw);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
-       priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;
-
-       tsf = priv->timestamp;
-
-       beacon_int = priv->beacon_int;
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (priv->iw_mode == NL80211_IFTYPE_STATION) {
-               if (beacon_int == 0) {
-                       priv->rxon_timing.beacon_interval = cpu_to_le16(100);
-                       priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
-               } else {
-                       priv->rxon_timing.beacon_interval =
-                               cpu_to_le16(beacon_int);
-                       priv->rxon_timing.beacon_interval =
-                           iwl3945_adjust_beacon_interval(
-                               le16_to_cpu(priv->rxon_timing.beacon_interval));
-               }
-
-               priv->rxon_timing.atim_window = 0;
-       } else {
-               priv->rxon_timing.beacon_interval =
-                       iwl3945_adjust_beacon_interval(conf->beacon_int);
-               /* TODO: we need to get atim_window from upper stack
-                * for now we set to 0 */
-               priv->rxon_timing.atim_window = 0;
-       }
-
-       interval_tm_unit =
-               (le16_to_cpu(priv->rxon_timing.beacon_interval) * 1024);
-       result = do_div(tsf, interval_tm_unit);
-       priv->rxon_timing.beacon_init_val =
-           cpu_to_le32((u32) ((u64) interval_tm_unit - result));
-
-       IWL_DEBUG_ASSOC(priv,
-               "beacon interval %d beacon timer %d beacon tim %d\n",
-               le16_to_cpu(priv->rxon_timing.beacon_interval),
-               le32_to_cpu(priv->rxon_timing.beacon_init_val),
-               le16_to_cpu(priv->rxon_timing.atim_window));
-}
-
-static int iwl3945_set_mode(struct iwl_priv *priv, int mode)
-{
-       if (mode == NL80211_IFTYPE_ADHOC) {
-               const struct iwl_channel_info *ch_info;
-
-               ch_info = iwl_get_channel_info(priv,
-                       priv->band,
-                       le16_to_cpu(priv->staging_rxon.channel));
-
-               if (!ch_info || !is_channel_ibss(ch_info)) {
-                       IWL_ERR(priv, "channel %d not IBSS channel\n",
-                                 le16_to_cpu(priv->staging_rxon.channel));
-                       return -EINVAL;
-               }
-       }
-
-       iwl_connection_init_rx_config(priv, mode);
-
-       iwl3945_clear_stations_table(priv);
-
-       /* don't commit rxon if rf-kill is on*/
-       if (!iwl_is_ready_rf(priv))
-               return -EAGAIN;
-
-       cancel_delayed_work(&priv->scan_check);
-       if (iwl_scan_cancel_timeout(priv, 100)) {
-               IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
-               IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-               return -EAGAIN;
-       }
-
-       iwl3945_commit_rxon(priv);
-
-       return 0;
-}
-
 static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
                                      struct ieee80211_tx_info *info,
-                                     struct iwl_cmd *cmd,
+                                     struct iwl_device_cmd *cmd,
                                      struct sk_buff *skb_frag,
                                      int sta_id)
 {
        struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-       struct iwl3945_hw_key *keyinfo =
-           &priv->stations_39[sta_id].keyinfo;
+       struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
 
        switch (keyinfo->alg) {
        case ALG_CCMP:
@@ -837,7 +404,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
  * handle build REPLY_TX command notification.
  */
 static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
-                                 struct iwl_cmd *cmd,
+                                 struct iwl_device_cmd *cmd,
                                  struct ieee80211_tx_info *info,
                                  struct ieee80211_hdr *hdr, u8 std_id)
 {
@@ -900,64 +467,6 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
        tx->next_frame_len = 0;
 }
 
-/**
- * iwl3945_get_sta_id - Find station's index within station table
- */
-static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
-{
-       int sta_id;
-       u16 fc = le16_to_cpu(hdr->frame_control);
-
-       /* 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_params.bcast_sta_id;
-
-       switch (priv->iw_mode) {
-
-       /* 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 NL80211_IFTYPE_STATION:
-               return IWL_AP_ID;
-
-       /* If we are an AP, then find the station, or use BCAST */
-       case NL80211_IFTYPE_AP:
-               sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
-               if (sta_id != IWL_INVALID_STATION)
-                       return sta_id;
-               return priv->hw_params.bcast_sta_id;
-
-       /* If this frame is going out to an IBSS network, find the station,
-        * or create a new station table entry */
-       case NL80211_IFTYPE_ADHOC: {
-               /* Create new station table entry */
-               sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
-               if (sta_id != IWL_INVALID_STATION)
-                       return sta_id;
-
-               sta_id = iwl3945_add_station(priv, hdr->addr1, 0, CMD_ASYNC);
-
-               if (sta_id != IWL_INVALID_STATION)
-                       return sta_id;
-
-               IWL_DEBUG_DROP(priv, "Station %pM not in station map. "
-                              "Defaulting to broadcast...\n",
-                              hdr->addr1);
-               iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
-               return priv->hw_params.bcast_sta_id;
-       }
-       /* If we are in monitor mode, use BCAST. This is required for
-        * packet injection. */
-       case NL80211_IFTYPE_MONITOR:
-               return priv->hw_params.bcast_sta_id;
-
-       default:
-               IWL_WARN(priv, "Unknown mode of operation: %d\n",
-                       priv->iw_mode);
-               return priv->hw_params.bcast_sta_id;
-       }
-}
-
 /*
  * start REPLY_TX command process
  */
@@ -968,11 +477,12 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        struct iwl3945_tx_cmd *tx;
        struct iwl_tx_queue *txq = NULL;
        struct iwl_queue *q = NULL;
-       struct iwl_cmd *out_cmd = NULL;
+       struct iwl_device_cmd *out_cmd;
+       struct iwl_cmd_meta *out_meta;
        dma_addr_t phys_addr;
        dma_addr_t txcmd_phys;
        int txq_id = skb_get_queue_mapping(skb);
-       u16 len, idx, len_org, hdr_len;
+       u16 len, idx, len_org, hdr_len; /* TODO: len_org is not used */
        u8 id;
        u8 unicast;
        u8 sta_id;
@@ -1009,9 +519,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
 #endif
 
-       /* drop all data frame if we are not associated */
+       /* drop all non-injected data frame if we are not associated */
        if (ieee80211_is_data(fc) &&
-           (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */
+           !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
            (!iwl_is_associated(priv) ||
             ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
                IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
@@ -1023,7 +533,10 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        hdr_len = ieee80211_hdrlen(fc);
 
        /* Find (or create) index into station table for destination station */
-       sta_id = iwl3945_get_sta_id(priv, hdr);
+       if (info->flags & IEEE80211_TX_CTL_INJECTED)
+               sta_id = priv->hw_params.bcast_sta_id;
+       else
+               sta_id = iwl_get_sta_id(priv, hdr);
        if (sta_id == IWL_INVALID_STATION) {
                IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
                               hdr->addr1);
@@ -1035,7 +548,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        if (ieee80211_is_data_qos(fc)) {
                qc = ieee80211_get_qos_ctl(hdr);
                tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-               seq_number = priv->stations_39[sta_id].tid[tid].seq_number &
+               if (unlikely(tid >= MAX_TID_COUNT))
+                       goto drop;
+               seq_number = priv->stations[sta_id].tid[tid].seq_number &
                                IEEE80211_SCTL_SEQ;
                hdr->seq_ctrl = cpu_to_le16(seq_number) |
                        (hdr->seq_ctrl &
@@ -1057,6 +572,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        /* Init first empty entry in queue's array of Tx/cmd buffers */
        out_cmd = txq->cmd[idx];
+       out_meta = &txq->meta[idx];
        tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
        memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
        memset(tx, 0, sizeof(*tx));
@@ -1074,6 +590,41 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        /* Copy MAC header from skb into command buffer */
        memcpy(tx->hdr, hdr, hdr_len);
 
+
+       if (info->control.hw_key)
+               iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
+
+       /* TODO need this for burst mode later on */
+       iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
+
+       /* set is_hcca to 0; it probably will never be implemented */
+       iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
+
+       /* Total # bytes to be transmitted */
+       len = (u16)skb->len;
+       tx->len = cpu_to_le16(len);
+
+       iwl_dbg_log_tx_data_frame(priv, len, hdr);
+       iwl_update_stats(priv, true, fc, len);
+       tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
+       tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
+
+       if (!ieee80211_has_morefrags(hdr->frame_control)) {
+               txq->need_update = 1;
+               if (qc)
+                       priv->stations[sta_id].tid[tid].seq_number = seq_number;
+       } else {
+               wait_write_ptr = 1;
+               txq->need_update = 0;
+       }
+
+       IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
+                    le16_to_cpu(out_cmd->hdr.sequence));
+       IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags));
+       iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
+       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
+                          ieee80211_hdrlen(fc));
+
        /*
         * Use the first empty entry in this queue's command buffer array
         * to contain the Tx command and MAC header concatenated together
@@ -1096,22 +647,18 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        /* Physical address of this Tx command's header (not MAC header!),
         * within command buffer array. */
-       txcmd_phys = pci_map_single(priv->pci_dev,
-                                   out_cmd, sizeof(struct iwl_cmd),
-                                   PCI_DMA_TODEVICE);
-       pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
-       pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
-       /* Add buffer containing Tx command and MAC(!) header to TFD's
-        * first entry */
-       txcmd_phys += offsetof(struct iwl_cmd, hdr);
+       txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
+                                   len, PCI_DMA_TODEVICE);
+       /* we do not map meta data ... so we can safely access address to
+        * provide to unmap command*/
+       pci_unmap_addr_set(out_meta, mapping, txcmd_phys);
+       pci_unmap_len_set(out_meta, len, len);
 
        /* Add buffer containing Tx command and MAC(!) header to TFD's
         * first entry */
        priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
                                                   txcmd_phys, len, 1, 0);
 
-       if (info->control.hw_key)
-               iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
 
        /* Set up TFD's 2nd entry to point directly to remainder of skb,
         * if any (802.11 null frames have no payload). */
@@ -1124,32 +671,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                                                           0, U32_PAD(len));
        }
 
-       /* Total # bytes to be transmitted */
-       len = (u16)skb->len;
-       tx->len = cpu_to_le16(len);
-
-       /* TODO need this for burst mode later on */
-       iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
-
-       /* set is_hcca to 0; it probably will never be implemented */
-       iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
-
-       tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
-       tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
-
-       if (!ieee80211_has_morefrags(hdr->frame_control)) {
-               txq->need_update = 1;
-               if (qc)
-                       priv->stations_39[sta_id].tid[tid].seq_number = seq_number;
-       } else {
-               wait_write_ptr = 1;
-               txq->need_update = 0;
-       }
-
-       iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
-
-       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
-                          ieee80211_hdrlen(fc));
 
        /* Tell device the write index *just past* this latest filled TFD */
        q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
@@ -1168,7 +689,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                        spin_unlock_irqrestore(&priv->lock, flags);
                }
 
-               ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb));
+               iwl_stop_queue(priv, skb_get_queue_mapping(skb));
        }
 
        return 0;
@@ -1241,7 +762,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
        struct iwl_host_cmd cmd = {
                .id = REPLY_SPECTRUM_MEASUREMENT_CMD,
                .data = (void *)&spectrum,
-               .meta.flags = CMD_WANT_SKB,
+               .flags = CMD_WANT_SKB,
        };
        u32 add_time = le64_to_cpu(params->start_time);
        int rc;
@@ -1282,7 +803,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
        if (rc)
                return rc;
 
-       res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+       res = (struct iwl_rx_packet *)cmd.reply_skb->data;
        if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
                IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
                rc = -EIO;
@@ -1305,7 +826,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
                break;
        }
 
-       dev_kfree_skb_any(cmd.meta.u.skb);
+       dev_kfree_skb_any(cmd.reply_skb);
 
        return rc;
 }
@@ -1414,7 +935,7 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
        u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
        unsigned long status = priv->status;
 
-       IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n",
+       IWL_WARN(priv, "Card state received: HW:%s SW:%s\n",
                          (flags & HW_CARD_DISABLED) ? "Kill" : "On",
                          (flags & SW_CARD_DISABLED) ? "Kill" : "On");
 
@@ -1427,18 +948,12 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
                clear_bit(STATUS_RF_KILL_HW, &priv->status);
 
 
-       if (flags & SW_CARD_DISABLED)
-               set_bit(STATUS_RF_KILL_SW, &priv->status);
-       else
-               clear_bit(STATUS_RF_KILL_SW, &priv->status);
-
        iwl_scan_cancel(priv);
 
        if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-            test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
-           (test_bit(STATUS_RF_KILL_SW, &status) !=
-            test_bit(STATUS_RF_KILL_SW, &priv->status)))
-               queue_work(priv->workqueue, &priv->rf_kill);
+            test_bit(STATUS_RF_KILL_HW, &priv->status)))
+               wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+                               test_bit(STATUS_RF_KILL_HW, &priv->status));
        else
                wake_up_interruptible(&priv->wait_command_queue);
 }
@@ -1594,7 +1109,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
 
        /* 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))
+       if ((rxq->write_actual != (rxq->write & ~0x7))
            || (abs(rxq->write - rxq->read) > 7)) {
                spin_lock_irqsave(&rxq->lock, flags);
                rxq->need_update = 1;
@@ -1615,30 +1130,54 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
  * Also restock the Rx queue via iwl3945_rx_queue_restock.
  * This is called as a scheduled work item (except for during initialization)
  */
-static void iwl3945_rx_allocate(struct iwl_priv *priv)
+static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
 {
        struct iwl_rx_queue *rxq = &priv->rxq;
        struct list_head *element;
        struct iwl_rx_mem_buffer *rxb;
+       struct sk_buff *skb;
        unsigned long flags;
-       spin_lock_irqsave(&rxq->lock, flags);
-       while (!list_empty(&rxq->rx_used)) {
-               element = rxq->rx_used.next;
-               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
 
+       while (1) {
+               spin_lock_irqsave(&rxq->lock, flags);
+
+               if (list_empty(&rxq->rx_used)) {
+                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       return;
+               }
+               spin_unlock_irqrestore(&rxq->lock, flags);
+
+               if (rxq->free_count > RX_LOW_WATERMARK)
+                       priority |= __GFP_NOWARN;
                /* Alloc a new receive buffer */
-               rxb->skb =
-                   alloc_skb(priv->hw_params.rx_buf_size,
-                               __GFP_NOWARN | GFP_ATOMIC);
-               if (!rxb->skb) {
+               skb = alloc_skb(priv->hw_params.rx_buf_size, priority);
+               if (!skb) {
                        if (net_ratelimit())
-                               IWL_CRIT(priv, ": Can not allocate SKB buffers\n");
+                               IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
+                       if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+                           net_ratelimit())
+                               IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
+                                        priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
+                                        rxq->free_count);
                        /* We don't reschedule replenish work here -- we will
                         * call the restock method and if it still needs
                         * more buffers it will schedule replenish */
                        break;
                }
 
+               spin_lock_irqsave(&rxq->lock, flags);
+               if (list_empty(&rxq->rx_used)) {
+                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       dev_kfree_skb_any(skb);
+                       return;
+               }
+               element = rxq->rx_used.next;
+               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+               list_del(element);
+               spin_unlock_irqrestore(&rxq->lock, flags);
+
+               rxb->skb = skb;
+
                /* 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
@@ -1647,44 +1186,98 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv)
                 */
                skb_reserve(rxb->skb, 4);
 
-               priv->alloc_rxb_skb++;
-               list_del(element);
-
                /* Get physical address of RB/SKB */
                rxb->real_dma_addr = pci_map_single(priv->pci_dev,
                                                rxb->skb->data,
                                                priv->hw_params.rx_buf_size,
                                                PCI_DMA_FROMDEVICE);
+
+               spin_lock_irqsave(&rxq->lock, flags);
                list_add_tail(&rxb->list, &rxq->rx_free);
+               priv->alloc_rxb_skb++;
                rxq->free_count++;
+               spin_unlock_irqrestore(&rxq->lock, flags);
        }
-       spin_unlock_irqrestore(&rxq->lock, flags);
 }
 
-/*
- * this should be called while priv->lock is locked
- */
-static void __iwl3945_rx_replenish(void *data)
+void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
 {
-       struct iwl_priv *priv = data;
+       unsigned long flags;
+       int i;
+       spin_lock_irqsave(&rxq->lock, flags);
+       INIT_LIST_HEAD(&rxq->rx_free);
+       INIT_LIST_HEAD(&rxq->rx_used);
+       /* Fill the rx_used queue with _all_ of the Rx buffers */
+       for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+               /* In the reset function, these buffers may have been allocated
+                * to an SKB, so we need to unmap and free potential storage */
+               if (rxq->pool[i].skb != NULL) {
+                       pci_unmap_single(priv->pci_dev,
+                                        rxq->pool[i].real_dma_addr,
+                                        priv->hw_params.rx_buf_size,
+                                        PCI_DMA_FROMDEVICE);
+                       priv->alloc_rxb_skb--;
+                       dev_kfree_skb(rxq->pool[i].skb);
+                       rxq->pool[i].skb = NULL;
+               }
+               list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+       }
 
-       iwl3945_rx_allocate(priv);
-       iwl3945_rx_queue_restock(priv);
+       /* 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;
+       rxq->free_count = 0;
+       rxq->write_actual = 0;
+       spin_unlock_irqrestore(&rxq->lock, flags);
 }
 
-
 void iwl3945_rx_replenish(void *data)
 {
        struct iwl_priv *priv = data;
        unsigned long flags;
 
-       iwl3945_rx_allocate(priv);
+       iwl3945_rx_allocate(priv, GFP_KERNEL);
 
        spin_lock_irqsave(&priv->lock, flags);
        iwl3945_rx_queue_restock(priv);
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
+static void iwl3945_rx_replenish_now(struct iwl_priv *priv)
+{
+       iwl3945_rx_allocate(priv, GFP_ATOMIC);
+
+       iwl3945_rx_queue_restock(priv);
+}
+
+
+/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
+ * 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
+ */
+static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+       int i;
+       for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+               if (rxq->pool[i].skb != NULL) {
+                       pci_unmap_single(priv->pci_dev,
+                                        rxq->pool[i].real_dma_addr,
+                                        priv->hw_params.rx_buf_size,
+                                        PCI_DMA_FROMDEVICE);
+                       dev_kfree_skb(rxq->pool[i].skb);
+               }
+       }
+
+       pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+                           rxq->dma_addr);
+       pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
+                           rxq->rb_stts, rxq->rb_stts_dma);
+       rxq->bd = NULL;
+       rxq->rb_stts  = NULL;
+}
+
+
 /* Convert linear signal-to-noise ratio into dB */
 static u8 ratio2dB[100] = {
 /*      0   1   2   3   4   5   6   7   8   9 */
@@ -1780,17 +1373,23 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
        unsigned long flags;
        u8 fill_rx = 0;
        u32 count = 8;
+       int total_empty = 0;
 
        /* uCode's read index (stored in shared DRAM) indicates the last Rx
         * buffer that the driver may process (last buffer filled by ucode). */
        r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
        i = rxq->read;
 
-       if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
+       /* calculate total frames need to be restock after handling RX */
+       total_empty = r - priv->rxq.write_actual;
+       if (total_empty < 0)
+               total_empty += RX_QUEUE_SIZE;
+
+       if (total_empty > (RX_QUEUE_SIZE / 2))
                fill_rx = 1;
        /* Rx interrupt, but nothing sent from uCode */
        if (i == r)
-               IWL_DEBUG(priv, IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
+               IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
 
        while (i != r) {
                rxb = rxq->queue[i];
@@ -1802,9 +1401,9 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
 
                rxq->queue[i] = NULL;
 
-               pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->real_dma_addr,
-                                           priv->hw_params.rx_buf_size,
-                                           PCI_DMA_FROMDEVICE);
+               pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
+                               priv->hw_params.rx_buf_size,
+                               PCI_DMA_FROMDEVICE);
                pkt = (struct iwl_rx_packet *)rxb->skb->data;
 
                /* Reclaim a command buffer only if this packet is a response
@@ -1821,14 +1420,13 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
                 *   handle those that need handling via function in
                 *   rx_handlers table.  See iwl3945_setup_rx_handlers() */
                if (priv->rx_handlers[pkt->hdr.cmd]) {
-                       IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR,
-                               "r = %d, i = %d, %s, 0x%02x\n", r, i,
+                       IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i,
                                get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
                        priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+                       priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
                } else {
                        /* No handling needed */
-                       IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR,
-                               "r %d i %d No handler needed for %s, 0x%02x\n",
+                       IWL_DEBUG_RX(priv, "r %d i %d No handler needed for %s, 0x%02x\n",
                                r, i, get_cmd_string(pkt->hdr.cmd),
                                pkt->hdr.cmd);
                }
@@ -1852,9 +1450,6 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
                        rxb->skb = NULL;
                }
 
-               pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
-                               priv->hw_params.rx_buf_size,
-                               PCI_DMA_FROMDEVICE);
                spin_lock_irqsave(&rxq->lock, flags);
                list_add_tail(&rxb->list, &priv->rxq.rx_used);
                spin_unlock_irqrestore(&rxq->lock, flags);
@@ -1865,7 +1460,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
                        count++;
                        if (count >= 8) {
                                priv->rxq.read = i;
-                               __iwl3945_rx_replenish(priv);
+                               iwl3945_rx_replenish_now(priv);
                                count = 0;
                        }
                }
@@ -1873,7 +1468,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
 
        /* Backtrack one entry */
        priv->rxq.read = i;
-       iwl3945_rx_queue_restock(priv);
+       if (fill_rx)
+               iwl3945_rx_replenish_now(priv);
+       else
+               iwl3945_rx_queue_restock(priv);
 }
 
 /* call this function to flush any scheduled tasklet */
@@ -1884,6 +1482,7 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv)
        tasklet_kill(&priv->irq_tasklet);
 }
 
+#ifdef CONFIG_IWLWIFI_DEBUG
 static const char *desc_lookup(int i)
 {
        switch (i) {
@@ -1907,12 +1506,11 @@ static const char *desc_lookup(int i)
 #define ERROR_START_OFFSET  (1 * sizeof(u32))
 #define ERROR_ELEM_SIZE     (7 * sizeof(u32))
 
-static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
+void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
 {
        u32 i;
        u32 desc, time, count, base, data1;
        u32 blink1, blink2, ilink1, ilink2;
-       int rc;
 
        base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
 
@@ -1921,11 +1519,6 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
                return;
        }
 
-       rc = iwl_grab_nic_access(priv);
-       if (rc) {
-               IWL_WARN(priv, "Can not read from adapter at this time.\n");
-               return;
-       }
 
        count = iwl_read_targ_mem(priv, base);
 
@@ -1960,8 +1553,6 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
                        ilink1, ilink2, data1);
        }
 
-       iwl_release_nic_access(priv);
-
 }
 
 #define EVENT_START_OFFSET  (6 * sizeof(u32))
@@ -1969,7 +1560,6 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
 /**
  * iwl3945_print_event_log - Dump error event log to syslog
  *
- * NOTE: Must be called with iwl_grab_nic_access() already obtained!
  */
 static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
                                u32 num_events, u32 mode)
@@ -2010,9 +1600,8 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
        }
 }
 
-static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
+void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
 {
-       int rc;
        u32 base;       /* SRAM byte address of event log header */
        u32 capacity;   /* event log capacity in # entries */
        u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
@@ -2026,12 +1615,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
                return;
        }
 
-       rc = iwl_grab_nic_access(priv);
-       if (rc) {
-               IWL_WARN(priv, "Can not read from adapter at this time.\n");
-               return;
-       }
-
        /* event log header */
        capacity = iwl_read_targ_mem(priv, base);
        mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
@@ -2043,7 +1626,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
        /* bail out if nothing in log */
        if (size == 0) {
                IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
-               iwl_release_nic_access(priv);
                return;
        }
 
@@ -2059,26 +1641,18 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
        /* (then/else) start at top of log */
        iwl3945_print_event_log(priv, 0, next_entry, mode);
 
-       iwl_release_nic_access(priv);
 }
-
-static void iwl3945_error_recovery(struct iwl_priv *priv)
+#else
+void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
 {
-       unsigned long flags;
-
-       memcpy(&priv->staging_rxon, &priv->recovery_rxon,
-              sizeof(priv->staging_rxon));
-       priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       iwl3945_commit_rxon(priv);
-
-       iwl3945_add_station(priv, priv->bssid, 1, 0);
+}
 
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
-       priv->error_recovering = 0;
-       spin_unlock_irqrestore(&priv->lock, flags);
+void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
+{
 }
 
+#endif
+
 static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 {
        u32 inta, handled = 0;
@@ -2103,7 +1677,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
        iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-       if (priv->debug_level & IWL_DL_ISR) {
+       if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
                /* just for debug */
                inta_mask = iwl_read32(priv, CSR_INT_MASK);
                IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -2122,11 +1696,12 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 
        /* Now service all interrupt bits discovered above. */
        if (inta & CSR_INT_BIT_HW_ERR) {
-               IWL_ERR(priv, "Microcode HW error detected.  Restarting.\n");
+               IWL_ERR(priv, "Hardware error detected.  Restarting.\n");
 
                /* Tell the device to stop sending interrupts */
                iwl_disable_interrupts(priv);
 
+               priv->isr_stats.hw++;
                iwl_irq_handle_error(priv);
 
                handled |= CSR_INT_BIT_HW_ERR;
@@ -2137,15 +1712,19 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
        }
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-       if (priv->debug_level & (IWL_DL_ISR)) {
+       if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
                /* NIC fires this, but we don't use it, redundant with WAKEUP */
-               if (inta & CSR_INT_BIT_SCD)
+               if (inta & CSR_INT_BIT_SCD) {
                        IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
                                      "the frame/frames.\n");
+                       priv->isr_stats.sch++;
+               }
 
                /* Alive notification via Rx interrupt will do the real work */
-               if (inta & CSR_INT_BIT_ALIVE)
+               if (inta & CSR_INT_BIT_ALIVE) {
                        IWL_DEBUG_ISR(priv, "Alive interrupt\n");
+                       priv->isr_stats.alive++;
+               }
        }
 #endif
        /* Safely ignore these bits for debug checks below */
@@ -2155,6 +1734,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
        if (inta & CSR_INT_BIT_SW_ERR) {
                IWL_ERR(priv, "Microcode SW error detected. "
                        "Restarting 0x%X.\n", inta);
+               priv->isr_stats.sw++;
+               priv->isr_stats.sw_err = inta;
                iwl_irq_handle_error(priv);
                handled |= CSR_INT_BIT_SW_ERR;
        }
@@ -2170,6 +1751,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
                iwl_txq_update_write_ptr(priv, &priv->txq[4]);
                iwl_txq_update_write_ptr(priv, &priv->txq[5]);
 
+               priv->isr_stats.wakeup++;
                handled |= CSR_INT_BIT_WAKEUP;
        }
 
@@ -2178,27 +1760,28 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
         * notifications from uCode come through here*/
        if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
                iwl3945_rx_handle(priv);
+               priv->isr_stats.rx++;
                handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
        }
 
        if (inta & CSR_INT_BIT_FH_TX) {
                IWL_DEBUG_ISR(priv, "Tx interrupt\n");
+               priv->isr_stats.tx++;
 
                iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
-               if (!iwl_grab_nic_access(priv)) {
-                       iwl_write_direct32(priv, FH39_TCSR_CREDIT
-                                            (FH39_SRVC_CHNL), 0x0);
-                       iwl_release_nic_access(priv);
-               }
+               iwl_write_direct32(priv, FH39_TCSR_CREDIT
+                                       (FH39_SRVC_CHNL), 0x0);
                handled |= CSR_INT_BIT_FH_TX;
        }
 
-       if (inta & ~handled)
+       if (inta & ~handled) {
                IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
+               priv->isr_stats.unhandled++;
+       }
 
-       if (inta & ~CSR_INI_SET_MASK) {
+       if (inta & ~priv->inta_mask) {
                IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
-                        inta & ~CSR_INI_SET_MASK);
+                        inta & ~priv->inta_mask);
                IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
        }
 
@@ -2208,7 +1791,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
                iwl_enable_interrupts(priv);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-       if (priv->debug_level & (IWL_DL_ISR)) {
+       if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
                inta = iwl_read32(priv, CSR_INT);
                inta_mask = iwl_read32(priv, CSR_INT_MASK);
                inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
@@ -2224,7 +1807,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
                                     u8 is_active, u8 n_probes,
                                     struct iwl3945_scan_channel *scan_ch)
 {
-       const struct ieee80211_channel *channels = NULL;
+       struct ieee80211_channel *chan;
        const struct ieee80211_supported_band *sband;
        const struct iwl_channel_info *ch_info;
        u16 passive_dwell = 0;
@@ -2235,19 +1818,19 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
        if (!sband)
                return 0;
 
-       channels = sband->channels;
-
        active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
        passive_dwell = iwl_get_passive_dwell_time(priv, band);
 
        if (passive_dwell <= active_dwell)
                passive_dwell = active_dwell + 1;
 
-       for (i = 0, added = 0; i < sband->n_channels; i++) {
-               if (channels[i].flags & IEEE80211_CHAN_DISABLED)
+       for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
+               chan = priv->scan_request->channels[i];
+
+               if (chan->band != band)
                        continue;
 
-               scan_ch->channel = channels[i].hw_value;
+               scan_ch->channel = chan->hw_value;
 
                ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);
                if (!is_channel_valid(ch_info)) {
@@ -2262,7 +1845,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
                 *  and use long active_dwell time.
                 */
                if (!is_active || is_channel_passive(ch_info) ||
-                   (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
+                   (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
                        scan_ch->type = 0;      /* passive */
                        if (IWL_UCODE_API(priv->ucode_ver) == 1)
                                scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
@@ -2362,10 +1945,6 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le
 
        IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
 
-       rc = iwl_grab_nic_access(priv);
-       if (rc)
-               return rc;
-
        iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
                               IWL39_RTC_INST_LOWER_BOUND);
 
@@ -2386,7 +1965,6 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le
                }
        }
 
-       iwl_release_nic_access(priv);
 
        if (!errcnt)
                IWL_DEBUG_INFO(priv,
@@ -2410,10 +1988,6 @@ static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32
 
        IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
 
-       rc = iwl_grab_nic_access(priv);
-       if (rc)
-               return rc;
-
        for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
                /* read data comes through single port, auto-incr addr */
                /* NOTE: Use the debugless read so we don't flood kernel log
@@ -2434,8 +2008,6 @@ static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32
                }
        }
 
-       iwl_release_nic_access(priv);
-
        return rc;
 }
 
@@ -2502,7 +2074,7 @@ static void iwl3945_nic_start(struct iwl_priv *priv)
  */
 static int iwl3945_read_ucode(struct iwl_priv *priv)
 {
-       struct iwl_ucode *ucode;
+       const struct iwl_ucode_header *ucode;
        int ret = -EINVAL, index;
        const struct firmware *ucode_raw;
        /* firmware file name contains uCode/driver compatibility version */
@@ -2543,26 +2115,28 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
                goto error;
 
        /* Make sure that we got at least our header! */
-       if (ucode_raw->size < sizeof(*ucode)) {
+       if (ucode_raw->size <  priv->cfg->ops->ucode->get_header_size(1)) {
                IWL_ERR(priv, "File size way too small!\n");
                ret = -EINVAL;
                goto err_release;
        }
 
        /* Data from ucode file:  header followed by uCode images */
-       ucode = (void *)ucode_raw->data;
+       ucode = (struct iwl_ucode_header *)ucode_raw->data;
 
        priv->ucode_ver = le32_to_cpu(ucode->ver);
        api_ver = IWL_UCODE_API(priv->ucode_ver);
-       inst_size = le32_to_cpu(ucode->inst_size);
-       data_size = le32_to_cpu(ucode->data_size);
-       init_size = le32_to_cpu(ucode->init_size);
-       init_data_size = le32_to_cpu(ucode->init_data_size);
-       boot_size = le32_to_cpu(ucode->boot_size);
+       inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
+       data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
+       init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
+       init_data_size =
+               priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
+       boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
+       src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
 
        /* api_ver should match the api version forming part of the
         * firmware filename ... but we don't check for that and only rely
-        * on the API version read from firware header from here on forward */
+        * on the API version read from firmware header from here on forward */
 
        if (api_ver < api_min || api_ver > api_max) {
                IWL_ERR(priv, "Driver unable to support your firmware API. "
@@ -2599,12 +2173,13 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
 
 
        /* Verify size of file vs. image size info in file's header */
-       if (ucode_raw->size < sizeof(*ucode) +
+       if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) +
                inst_size + data_size + init_size +
                init_data_size + boot_size) {
 
-               IWL_DEBUG_INFO(priv, "uCode file size %zd too small\n",
-                              ucode_raw->size);
+               IWL_DEBUG_INFO(priv,
+                       "uCode file size %zd does not match expected size\n",
+                       ucode_raw->size);
                ret = -EINVAL;
                goto err_release;
        }
@@ -2687,44 +2262,44 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
        /* 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;
+       len = inst_size;
        IWL_DEBUG_INFO(priv,
                "Copying (but not loading) uCode instr len %zd\n", len);
        memcpy(priv->ucode_code.v_addr, src, len);
+       src += len;
+
        IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
                priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
 
        /* Runtime data (2nd block)
         * NOTE:  Copy into backup buffer will be done in iwl3945_up()  */
-       src = &ucode->data[inst_size];
-       len = priv->ucode_data.len;
+       len = data_size;
        IWL_DEBUG_INFO(priv,
                "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);
+       src += len;
 
        /* Initialization instructions (3rd block) */
        if (init_size) {
-               src = &ucode->data[inst_size + data_size];
-               len = priv->ucode_init.len;
+               len = init_size;
                IWL_DEBUG_INFO(priv,
                        "Copying (but not loading) init instr len %zd\n", len);
                memcpy(priv->ucode_init.v_addr, src, len);
+               src += len;
        }
 
        /* Initialization data (4th block) */
        if (init_data_size) {
-               src = &ucode->data[inst_size + data_size + init_size];
-               len = priv->ucode_init_data.len;
+               len = init_data_size;
                IWL_DEBUG_INFO(priv,
                        "Copying (but not loading) init data len %zd\n", len);
                memcpy(priv->ucode_init_data.v_addr, src, len);
+               src += len;
        }
 
        /* Bootstrap instructions (5th block) */
-       src = &ucode->data[inst_size + data_size + init_size + init_data_size];
-       len = priv->ucode_boot.len;
+       len = boot_size;
        IWL_DEBUG_INFO(priv,
                "Copying (but not loading) boot instr len %zd\n", len);
        memcpy(priv->ucode_boot.v_addr, src, len);
@@ -2759,20 +2334,11 @@ static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv)
 {
        dma_addr_t pinst;
        dma_addr_t pdata;
-       int rc = 0;
-       unsigned long flags;
 
        /* bits 31:0 for 3945 */
        pinst = priv->ucode_code.p_addr;
        pdata = priv->ucode_data_backup.p_addr;
 
-       spin_lock_irqsave(&priv->lock, flags);
-       rc = iwl_grab_nic_access(priv);
-       if (rc) {
-               spin_unlock_irqrestore(&priv->lock, flags);
-               return rc;
-       }
-
        /* Tell bootstrap uCode where to find image to load */
        iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
        iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
@@ -2784,13 +2350,9 @@ static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv)
        iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
                                 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
 
-       iwl_release_nic_access(priv);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
 
-       return rc;
+       return 0;
 }
 
 /**
@@ -2836,11 +2398,6 @@ static void iwl3945_init_alive_start(struct iwl_priv *priv)
        queue_work(priv->workqueue, &priv->restart);
 }
 
-
-/* temporary */
-static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw,
-                                    struct sk_buff *skb);
-
 /**
  * iwl3945_alive_start - called after REPLY_ALIVE notification received
  *                   from protocol/runtime uCode (initialization uCode's
@@ -2848,7 +2405,6 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw,
  */
 static void iwl3945_alive_start(struct iwl_priv *priv)
 {
-       int rc = 0;
        int thermal_spin = 0;
        u32 rfkill;
 
@@ -2871,17 +2427,10 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
                goto restart;
        }
 
-       iwl3945_clear_stations_table(priv);
-
-       rc = iwl_grab_nic_access(priv);
-       if (rc) {
-               IWL_WARN(priv, "Can not read RFKILL status from adapter\n");
-               return;
-       }
+       iwl_clear_stations_table(priv);
 
        rfkill = iwl_read_prph(priv, APMG_RFKILL_REG);
        IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill);
-       iwl_release_nic_access(priv);
 
        if (rfkill & 0x1) {
                clear_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -2901,9 +2450,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
        /* 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);
-
        if (iwl_is_rfkill(priv))
                return;
 
@@ -2918,8 +2464,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
                struct iwl3945_rxon_cmd *active_rxon =
                                (struct iwl3945_rxon_cmd *)(&priv->active_rxon);
 
-               memcpy(&priv->staging_rxon, &priv->active_rxon,
-                      sizeof(priv->staging_rxon));
+               priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
                active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
        } else {
                /* Initialize our rx_config data */
@@ -2930,7 +2475,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
        iwl_send_bt_config(priv);
 
        /* Configure the adapter for unassociated operation */
-       iwl3945_commit_rxon(priv);
+       iwlcore_commit_rxon(priv);
 
        iwl3945_reg_txpower_periodic(priv);
 
@@ -2940,17 +2485,17 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
        set_bit(STATUS_READY, &priv->status);
        wake_up_interruptible(&priv->wait_command_queue);
 
-       if (priv->error_recovering)
-               iwl3945_error_recovery(priv);
-
        /* reassociate for ADHOC mode */
        if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
                struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
                                                                priv->vif);
                if (beacon)
-                       iwl3945_mac_beacon_update(priv->hw, beacon);
+                       iwl_mac_beacon_update(priv->hw, beacon);
        }
 
+       if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status))
+               iwl_set_mode(priv, priv->iw_mode);
+
        return;
 
  restart:
@@ -2973,7 +2518,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
                set_bit(STATUS_EXIT_PENDING, &priv->status);
 
        iwl3945_led_unregister(priv);
-       iwl3945_clear_stations_table(priv);
+       iwl_clear_stations_table(priv);
 
        /* Unblock any waiting calls */
        wake_up_interruptible_all(&priv->wait_command_queue);
@@ -2996,31 +2541,23 @@ static void __iwl3945_down(struct iwl_priv *priv)
                ieee80211_stop_queues(priv->hw);
 
        /* If we have not previously called iwl3945_init() then
-        * clear all bits but the RF Kill and SUSPEND bits and return */
+        * clear all bits but the RF Kill bits and return */
        if (!iwl_is_init(priv)) {
                priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
                                        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_EXIT_PENDING, &priv->status) <<
                                        STATUS_EXIT_PENDING;
                goto exit;
        }
 
-       /* ...otherwise clear out all the status bits but the RF Kill and
-        * SUSPEND bits and continue taking the NIC down. */
+       /* ...otherwise clear out all the status bits but the RF Kill
+        * bit and continue taking the NIC down. */
        priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
                                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) <<
                                STATUS_FW_ERROR |
                        test_bit(STATUS_EXIT_PENDING, &priv->status) <<
@@ -3034,17 +2571,12 @@ static void __iwl3945_down(struct iwl_priv *priv)
        iwl3945_hw_txq_ctx_stop(priv);
        iwl3945_hw_rxq_stop(priv);
 
-       spin_lock_irqsave(&priv->lock, flags);
-       if (!iwl_grab_nic_access(priv)) {
-               iwl_write_prph(priv, APMG_CLK_DIS_REG,
-                                        APMG_CLK_VAL_DMA_CLK_RQT);
-               iwl_release_nic_access(priv);
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
+       iwl_write_prph(priv, APMG_CLK_DIS_REG,
+                               APMG_CLK_VAL_DMA_CLK_RQT);
 
        udelay(5);
 
-       if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
+       if (exit_pending)
                priv->cfg->ops->lib->apm_ops.stop(priv);
        else
                priv->cfg->ops->lib->apm_ops.reset(priv);
@@ -3080,12 +2612,6 @@ static int __iwl3945_up(struct iwl_priv *priv)
                return -EIO;
        }
 
-       if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
-               IWL_WARN(priv, "Radio disabled by SW RF kill (module "
-                           "parameter)\n");
-               return -ENODEV;
-       }
-
        if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
                IWL_ERR(priv, "ucode not available for device bring up\n");
                return -EIO;
@@ -3097,10 +2623,8 @@ static int __iwl3945_up(struct iwl_priv *priv)
                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_WARN(priv, "Radio disabled by HW RF Kill switch\n");
-                       return -ENODEV;
-               }
+               IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
+               return -ENODEV;
        }
 
        iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
@@ -3136,7 +2660,7 @@ static int __iwl3945_up(struct iwl_priv *priv)
 
        for (i = 0; i < MAX_HW_RESTARTS; i++) {
 
-               iwl3945_clear_stations_table(priv);
+               iwl_clear_stations_table(priv);
 
                /* load bootstrap state machine,
                 * load bootstrap program into processor's memory,
@@ -3204,15 +2728,14 @@ static void iwl3945_rfkill_poll(struct work_struct *data)
 {
        struct iwl_priv *priv =
            container_of(data, struct iwl_priv, rfkill_poll.work);
-       unsigned long status = priv->status;
 
        if (iwl_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_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status))
-               queue_work(priv->workqueue, &priv->rf_kill);
+       wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+                       test_bit(STATUS_RF_KILL_HW, &priv->status));
 
        queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
                           round_jiffies_relative(2 * HZ));
@@ -3227,19 +2750,21 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        struct iwl_host_cmd cmd = {
                .id = REPLY_SCAN_CMD,
                .len = sizeof(struct iwl3945_scan_cmd),
-               .meta.flags = CMD_SIZE_HUGE,
+               .flags = CMD_SIZE_HUGE,
        };
        int rc = 0;
        struct iwl3945_scan_cmd *scan;
        struct ieee80211_conf *conf = NULL;
-       u8 n_probes = 2;
+       u8 n_probes = 0;
        enum ieee80211_band band;
-       DECLARE_SSID_BUF(ssid);
+       bool is_active = false;
 
        conf = ieee80211_get_hw_conf(priv->hw);
 
        mutex_lock(&priv->mutex);
 
+       cancel_delayed_work(&priv->scan_check);
+
        if (!iwl_is_ready(priv)) {
                IWL_WARN(priv, "request scan called when driver not ready.\n");
                goto done;
@@ -3333,18 +2858,25 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                               scan_suspend_time, interval);
        }
 
-       /* We should add the ability for user to lock to PASSIVE ONLY */
-       if (priv->one_direct_scan) {
-               IWL_DEBUG_SCAN(priv, "Kicking off one direct scan for '%s'\n",
-                               print_ssid(ssid, priv->direct_ssid,
-                               priv->direct_ssid_len));
-               scan->direct_scan[0].id = WLAN_EID_SSID;
-               scan->direct_scan[0].len = priv->direct_ssid_len;
-               memcpy(scan->direct_scan[0].ssid,
-                      priv->direct_ssid, priv->direct_ssid_len);
-               n_probes++;
+       if (priv->scan_request->n_ssids) {
+               int i, p = 0;
+               IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
+               for (i = 0; i < priv->scan_request->n_ssids; i++) {
+                       /* always does wildcard anyway */
+                       if (!priv->scan_request->ssids[i].ssid_len)
+                               continue;
+                       scan->direct_scan[p].id = WLAN_EID_SSID;
+                       scan->direct_scan[p].len =
+                               priv->scan_request->ssids[i].ssid_len;
+                       memcpy(scan->direct_scan[p].ssid,
+                              priv->scan_request->ssids[i].ssid,
+                              priv->scan_request->ssids[i].ssid_len);
+                       n_probes++;
+                       p++;
+               }
+               is_active = true;
        } else
-               IWL_DEBUG_SCAN(priv, "Kicking off one indirect scan.\n");
+               IWL_DEBUG_SCAN(priv, "Kicking off passive scan.\n");
 
        /* We don't build a direct scan probe request; the uCode will do
         * that based on the direct_mask added to each channel entry */
@@ -3361,7 +2893,12 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                band = IEEE80211_BAND_2GHZ;
        } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
                scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
-               scan->good_CRC_th = IWL_GOOD_CRC_TH;
+               /*
+                * If active scaning is requested but a certain channel
+                * is marked passive, we can do active scanning if we
+                * detect transmissions.
+                */
+               scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
                band = IEEE80211_BAND_5GHZ;
        } else {
                IWL_WARN(priv, "Invalid scan band count\n");
@@ -3369,19 +2906,20 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        }
 
        scan->tx_cmd.len = cpu_to_le16(
-               iwl_fill_probe_req(priv, band,
-                                  (struct ieee80211_mgmt *)scan->data,
-                                  IWL_MAX_SCAN_SIZE - sizeof(*scan)));
+                       iwl_fill_probe_req(priv,
+                               (struct ieee80211_mgmt *)scan->data,
+                               priv->scan_request->ie,
+                               priv->scan_request->ie_len,
+                               IWL_MAX_SCAN_SIZE - sizeof(*scan)));
 
        /* select Rx antennas */
        scan->flags |= iwl3945_get_antenna_flags(priv);
 
-       if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
+       if (iwl_is_monitor_mode(priv))
                scan->filter_flags = RXON_FILTER_PROMISC_MSK;
 
        scan->channel_count =
-               iwl3945_get_channels_for_scan(priv, band, 1, /* active */
-                                             n_probes,
+               iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
                        (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
 
        if (scan->channel_count == 0) {
@@ -3429,7 +2967,6 @@ static void iwl3945_bg_up(struct work_struct *data)
        mutex_lock(&priv->mutex);
        __iwl3945_up(priv);
        mutex_unlock(&priv->mutex);
-       iwl_rfkill_set_hw_state(priv);
 }
 
 static void iwl3945_bg_restart(struct work_struct *data)
@@ -3439,8 +2976,17 @@ static void iwl3945_bg_restart(struct work_struct *data)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       iwl3945_down(priv);
-       queue_work(priv->workqueue, &priv->up);
+       if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+               mutex_lock(&priv->mutex);
+               priv->vif = NULL;
+               priv->is_open = 0;
+               mutex_unlock(&priv->mutex);
+               iwl3945_down(priv);
+               ieee80211_restart_hw(priv->hw);
+       } else {
+               iwl3945_down(priv);
+               queue_work(priv->workqueue, &priv->up);
+       }
 }
 
 static void iwl3945_bg_rx_replenish(struct work_struct *data)
@@ -3458,7 +3004,7 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
 
 #define IWL_DELAY_NEXT_SCAN (HZ*2)
 
-static void iwl3945_post_associate(struct iwl_priv *priv)
+void iwl3945_post_associate(struct iwl_priv *priv)
 {
        int rc = 0;
        struct ieee80211_conf *conf = NULL;
@@ -3483,10 +3029,10 @@ static void iwl3945_post_associate(struct iwl_priv *priv)
        conf = ieee80211_get_hw_conf(priv->hw);
 
        priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       iwl3945_commit_rxon(priv);
+       iwlcore_commit_rxon(priv);
 
        memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
-       iwl3945_setup_rxon_timing(priv);
+       iwl_setup_rxon_timing(priv);
        rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
                              sizeof(priv->rxon_timing), &priv->rxon_timing);
        if (rc)
@@ -3516,7 +3062,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv)
 
        }
 
-       iwl3945_commit_rxon(priv);
+       iwlcore_commit_rxon(priv);
 
        switch (priv->iw_mode) {
        case NL80211_IFTYPE_STATION:
@@ -3526,7 +3072,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv)
        case NL80211_IFTYPE_ADHOC:
 
                priv->assoc_id = 1;
-               iwl3945_add_station(priv, priv->bssid, 0, 0);
+               iwl_add_station(priv, priv->bssid, 0, CMD_SYNC, NULL);
                iwl3945_sync_sta(priv, IWL_STA_ID,
                                 (priv->band == IEEE80211_BAND_5GHZ) ?
                                 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
@@ -3548,8 +3094,6 @@ static void iwl3945_post_associate(struct iwl_priv *priv)
        priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
 }
 
-static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
-
 /*****************************************************************************
  *
  * mac80211 entry point functions
@@ -3568,7 +3112,6 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
        /* we should be verifying the device is ready to be opened */
        mutex_lock(&priv->mutex);
 
-       memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
        /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
         * ucode filename and max sizes are card-specific. */
 
@@ -3585,16 +3128,11 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
 
        mutex_unlock(&priv->mutex);
 
-       iwl_rfkill_set_hw_state(priv);
-
        if (ret)
                goto out_release_irq;
 
        IWL_DEBUG_INFO(priv, "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,
@@ -3673,144 +3211,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
        return NETDEV_TX_OK;
 }
 
-static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
-                                struct ieee80211_if_init_conf *conf)
-{
-       struct iwl_priv *priv = hw->priv;
-       unsigned long flags;
-
-       IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type);
-
-       if (priv->vif) {
-               IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
-               return -EOPNOTSUPP;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->vif = conf->vif;
-       priv->iw_mode = conf->type;
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       mutex_lock(&priv->mutex);
-
-       if (conf->mac_addr) {
-               IWL_DEBUG_MAC80211(priv, "Set: %pM\n", conf->mac_addr);
-               memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
-       }
-
-       if (iwl_is_ready(priv))
-               iwl3945_set_mode(priv, conf->type);
-
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       return 0;
-}
-
-/**
- * iwl3945_mac_config - mac80211 config callback
- *
- * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
- * be set inappropriately and the driver currently sets the hardware up to
- * use it whenever needed.
- */
-static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
-{
-       struct iwl_priv *priv = hw->priv;
-       const struct iwl_channel_info *ch_info;
-       struct ieee80211_conf *conf = &hw->conf;
-       unsigned long flags;
-       int ret = 0;
-
-       mutex_lock(&priv->mutex);
-       IWL_DEBUG_MAC80211(priv, "enter to channel %d\n",
-                               conf->channel->hw_value);
-
-       if (!iwl_is_ready(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-               ret = -EIO;
-               goto out;
-       }
-
-       if (unlikely(!iwl3945_mod_params.disable_hw_scan &&
-                    test_bit(STATUS_SCANNING, &priv->status))) {
-               IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
-               set_bit(STATUS_CONF_PENDING, &priv->status);
-               mutex_unlock(&priv->mutex);
-               return 0;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       ch_info = iwl_get_channel_info(priv, conf->channel->band,
-                                      conf->channel->hw_value);
-       if (!is_channel_valid(ch_info)) {
-               IWL_DEBUG_SCAN(priv,
-                               "Channel %d [%d] is INVALID for this band.\n",
-                               conf->channel->hw_value, conf->channel->band);
-               IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
-               spin_unlock_irqrestore(&priv->lock, flags);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       iwl_set_rxon_channel(priv, conf->channel);
-
-       iwl_set_flags_for_band(priv, conf->channel->band);
-
-       /* The list of supported rates and rate mask can be different
-        * for each phymode; since the phymode may have changed, reset
-        * the rate mask to what mac80211 lists */
-       iwl_set_rate(priv);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-#ifdef IEEE80211_CONF_CHANNEL_SWITCH
-       if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
-               iwl3945_hw_channel_switch(priv, conf->channel);
-               goto out;
-       }
-#endif
-
-       if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
-               if (conf->radio_enabled &&
-                   iwl_radio_kill_sw_enable_radio(priv)) {
-                       IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - "
-                                                "waiting for uCode\n");
-                       goto out;
-               }
-
-               if (!conf->radio_enabled) {
-                       iwl_radio_kill_sw_disable_radio(priv);
-                       IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n");
-                       goto out;
-               }
-       }
-
-       if (iwl_is_rfkill(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF kill\n");
-               ret = -EIO;
-               goto out;
-       }
-
-       iwl_set_rate(priv);
-
-       if (memcmp(&priv->active_rxon,
-                  &priv->staging_rxon, sizeof(priv->staging_rxon)))
-               iwl3945_commit_rxon(priv);
-       else
-               IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration\n");
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-out:
-       clear_bit(STATUS_CONF_PENDING, &priv->status);
-       mutex_unlock(&priv->mutex);
-       return ret;
-}
-
-static void iwl3945_config_ap(struct iwl_priv *priv)
+void iwl3945_config_ap(struct iwl_priv *priv)
 {
        int rc = 0;
 
@@ -3822,11 +3223,11 @@ static void iwl3945_config_ap(struct iwl_priv *priv)
 
                /* RXON - unassoc (to set timing command) */
                priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-               iwl3945_commit_rxon(priv);
+               iwlcore_commit_rxon(priv);
 
                /* RXON Timing */
                memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
-               iwl3945_setup_rxon_timing(priv);
+               iwl_setup_rxon_timing(priv);
                rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
                                      sizeof(priv->rxon_timing),
                                      &priv->rxon_timing);
@@ -3834,221 +3235,38 @@ static void iwl3945_config_ap(struct iwl_priv *priv)
                        IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
                                        "Attempting to continue.\n");
 
-               /* FIXME: what should be the assoc_id for AP? */
-               priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
-               if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
-                       priv->staging_rxon.flags |=
-                               RXON_FLG_SHORT_PREAMBLE_MSK;
-               else
-                       priv->staging_rxon.flags &=
-                               ~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-               if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
-                       if (priv->assoc_capability &
-                               WLAN_CAPABILITY_SHORT_SLOT_TIME)
-                               priv->staging_rxon.flags |=
-                                       RXON_FLG_SHORT_SLOT_MSK;
-                       else
-                               priv->staging_rxon.flags &=
-                                       ~RXON_FLG_SHORT_SLOT_MSK;
-
-                       if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
-                               priv->staging_rxon.flags &=
-                                       ~RXON_FLG_SHORT_SLOT_MSK;
-               }
-               /* restore RXON assoc */
-               priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
-               iwl3945_commit_rxon(priv);
-               iwl3945_add_station(priv, iwl_bcast_addr, 0, 0);
-       }
-       iwl3945_send_beacon_cmd(priv);
-
-       /* FIXME - we need to add code here to detect a totally new
-        * configuration, reset the AP, unassoc, rxon timing, assoc,
-        * clear sta table, add BCAST sta... */
-}
-
-static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
-                                       struct ieee80211_vif *vif,
-                                       struct ieee80211_if_conf *conf)
-{
-       struct iwl_priv *priv = hw->priv;
-       int rc;
-
-       if (conf == NULL)
-               return -EIO;
-
-       if (priv->vif != vif) {
-               IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n");
-               return 0;
-       }
-
-       /* handle this temporarily here */
-       if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
-           conf->changed & IEEE80211_IFCC_BEACON) {
-               struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
-               if (!beacon)
-                       return -ENOMEM;
-               mutex_lock(&priv->mutex);
-               rc = iwl3945_mac_beacon_update(hw, beacon);
-               mutex_unlock(&priv->mutex);
-               if (rc)
-                       return rc;
-       }
-
-       if (!iwl_is_alive(priv))
-               return -EAGAIN;
-
-       mutex_lock(&priv->mutex);
-
-       if (conf->bssid)
-               IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid);
-
-/*
- * very dubious code was here; the probe filtering flag is never set:
- *
-       if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
-           !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
- */
-
-       if (priv->iw_mode == NL80211_IFTYPE_AP) {
-               if (!conf->bssid) {
-                       conf->bssid = priv->mac_addr;
-                       memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
-                       IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n",
-                                          conf->bssid);
-               }
-               if (priv->ibss_beacon)
-                       dev_kfree_skb(priv->ibss_beacon);
-
-               priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
-       }
-
-       if (iwl_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
-                * then we need to cancel it else the RXON below will fail. */
-               if (iwl_scan_cancel_timeout(priv, 100)) {
-                       IWL_WARN(priv, "Aborted scan still in progress "
-                                   "after 100ms\n");
-                       IWL_DEBUG_MAC80211(priv, "leaving:scan abort failed\n");
-                       mutex_unlock(&priv->mutex);
-                       return -EAGAIN;
-               }
-               memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN);
-
-               /* TODO: Audit driver for usage of these members and see
-                * if mac80211 deprecates them (priv->bssid looks like it
-                * shouldn't be there, but I haven't scanned the IBSS code
-                * to verify) - jpk */
-               memcpy(priv->bssid, conf->bssid, ETH_ALEN);
-
-               if (priv->iw_mode == NL80211_IFTYPE_AP)
-                       iwl3945_config_ap(priv);
-               else {
-                       rc = iwl3945_commit_rxon(priv);
-                       if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
-                               iwl3945_add_station(priv,
-                                       priv->active_rxon.bssid_addr, 1, 0);
-               }
-
-       } else {
-               iwl_scan_cancel_timeout(priv, 100);
-               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-               iwl3945_commit_rxon(priv);
-       }
-
- done:
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       mutex_unlock(&priv->mutex);
-
-       return 0;
-}
-
-static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
-                                    struct ieee80211_if_init_conf *conf)
-{
-       struct iwl_priv *priv = hw->priv;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       mutex_lock(&priv->mutex);
-
-       if (iwl_is_ready_rf(priv)) {
-               iwl_scan_cancel_timeout(priv, 100);
-               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);
-       }
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
-#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
-
-static void iwl3945_bss_info_changed(struct ieee80211_hw *hw,
-                                    struct ieee80211_vif *vif,
-                                    struct ieee80211_bss_conf *bss_conf,
-                                    u32 changes)
-{
-       struct iwl_priv *priv = hw->priv;
-
-       IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
-
-       if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-               IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
-                                  bss_conf->use_short_preamble);
-               if (bss_conf->use_short_preamble)
-                       priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+               /* FIXME: what should be the assoc_id for AP? */
+               priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
+               if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+                       priv->staging_rxon.flags |=
+                               RXON_FLG_SHORT_PREAMBLE_MSK;
                else
                        priv->staging_rxon.flags &=
                                ~RXON_FLG_SHORT_PREAMBLE_MSK;
-       }
 
-       if (changes & BSS_CHANGED_ERP_CTS_PROT) {
-               IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n",
-                                  bss_conf->use_cts_prot);
-               if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
-                       priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
-               else
-                       priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
-       }
+               if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
+                       if (priv->assoc_capability &
+                               WLAN_CAPABILITY_SHORT_SLOT_TIME)
+                               priv->staging_rxon.flags |=
+                                       RXON_FLG_SHORT_SLOT_MSK;
+                       else
+                               priv->staging_rxon.flags &=
+                                       ~RXON_FLG_SHORT_SLOT_MSK;
 
-       if (changes & BSS_CHANGED_ASSOC) {
-               IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
-               /* This should never happen as this function should
-                * never be called from interrupt context. */
-               if (WARN_ON_ONCE(in_interrupt()))
-                       return;
-               if (bss_conf->assoc) {
-                       priv->assoc_id = bss_conf->aid;
-                       priv->beacon_int = bss_conf->beacon_int;
-                       priv->timestamp = bss_conf->timestamp;
-                       priv->assoc_capability = bss_conf->assoc_capability;
-                       priv->power_data.dtim_period = bss_conf->dtim_period;
-                       priv->next_scan_jiffies = jiffies +
-                                       IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
-                       mutex_lock(&priv->mutex);
-                       iwl3945_post_associate(priv);
-                       mutex_unlock(&priv->mutex);
-               } else {
-                       priv->assoc_id = 0;
-                       IWL_DEBUG_MAC80211(priv,
-                                       "DISASSOC %d\n", bss_conf->assoc);
+                       if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
+                               priv->staging_rxon.flags &=
+                                       ~RXON_FLG_SHORT_SLOT_MSK;
                }
-       } else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
-                       IWL_DEBUG_MAC80211(priv,
-                                       "Associated Changes %d\n", changes);
-                       iwl3945_send_rxon_assoc(priv);
+               /* restore RXON assoc */
+               priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+               iwlcore_commit_rxon(priv);
+               iwl_add_station(priv, iwl_bcast_addr, 0, CMD_SYNC, NULL);
        }
+       iwl3945_send_beacon_cmd(priv);
 
+       /* FIXME - we need to add code here to detect a totally new
+        * configuration, reset the AP, unassoc, rxon timing, assoc,
+        * clear sta table, add BCAST sta... */
 }
 
 static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -4073,9 +3291,9 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        static_key = !iwl_is_associated(priv);
 
        if (!static_key) {
-               sta_id = iwl3945_hw_find_station(priv, addr);
+               sta_id = iwl_find_station(priv, addr);
                if (sta_id == IWL_INVALID_STATION) {
-                       IWL_DEBUG_MAC80211(priv, "leave - %pMnot in station map.\n",
+                       IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
                                            addr);
                        return -EINVAL;
                }
@@ -4109,185 +3327,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        return ret;
 }
 
-static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
-                          const struct ieee80211_tx_queue_params *params)
-{
-       struct iwl_priv *priv = hw->priv;
-       unsigned long flags;
-       int q;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (!iwl_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-               return -EIO;
-       }
-
-       if (queue >= AC_NUM) {
-               IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue);
-               return 0;
-       }
-
-       q = AC_NUM - 1 - queue;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min);
-       priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
-       priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
-       priv->qos_data.def_qos_parm.ac[q].edca_txop =
-                       cpu_to_le16((params->txop * 32));
-
-       priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
-       priv->qos_data.qos_active = 1;
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       mutex_lock(&priv->mutex);
-       if (priv->iw_mode == NL80211_IFTYPE_AP)
-               iwl_activate_qos(priv, 1);
-       else if (priv->assoc_id && iwl_is_associated(priv))
-               iwl_activate_qos(priv, 0);
-
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       return 0;
-}
-
-static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw,
-                               struct ieee80211_tx_queue_stats *stats)
-{
-       struct iwl_priv *priv = hw->priv;
-       int i, avail;
-       struct iwl_tx_queue *txq;
-       struct iwl_queue *q;
-       unsigned long flags;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (!iwl_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-               return -EIO;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       for (i = 0; i < AC_NUM; i++) {
-               txq = &priv->txq[i];
-               q = &txq->q;
-               avail = iwl_queue_space(q);
-
-               stats[i].len = q->n_window - avail;
-               stats[i].limit = q->n_window - q->high_mark;
-               stats[i].count = q->n_window;
-
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-       return 0;
-}
-
-static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
-{
-       struct iwl_priv *priv = hw->priv;
-       unsigned long flags;
-
-       mutex_lock(&priv->mutex);
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       iwl_reset_qos(priv);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->assoc_id = 0;
-       priv->assoc_capability = 0;
-
-       /* new association get rid of ibss beacon skb */
-       if (priv->ibss_beacon)
-               dev_kfree_skb(priv->ibss_beacon);
-
-       priv->ibss_beacon = NULL;
-
-       priv->beacon_int = priv->hw->conf.beacon_int;
-       priv->timestamp = 0;
-       if ((priv->iw_mode == NL80211_IFTYPE_STATION))
-               priv->beacon_int = 0;
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (!iwl_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-               mutex_unlock(&priv->mutex);
-               return;
-       }
-
-       /* we are restarting association process
-        * clear RXON_FILTER_ASSOC_MSK bit
-       */
-       if (priv->iw_mode != NL80211_IFTYPE_AP) {
-               iwl_scan_cancel_timeout(priv, 100);
-               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-               iwl3945_commit_rxon(priv);
-       }
-
-       /* Per mac80211.h: This is only used in IBSS mode... */
-       if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
-
-               IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n");
-               mutex_unlock(&priv->mutex);
-               return;
-       }
-
-       iwl_set_rate(priv);
-
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-}
-
-static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-       struct iwl_priv *priv = hw->priv;
-       unsigned long flags;
-       __le64 timestamp;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (!iwl_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-               return -EIO;
-       }
-
-       if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
-               IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n");
-               return -EIO;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       if (priv->ibss_beacon)
-               dev_kfree_skb(priv->ibss_beacon);
-
-       priv->ibss_beacon = skb;
-
-       priv->assoc_id = 0;
-       timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
-       priv->timestamp = le64_to_cpu(timestamp);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       iwl_reset_qos(priv);
-
-       iwl3945_post_associate(priv);
-
-
-       return 0;
-}
-
 /*****************************************************************************
  *
  * sysfs attributes
@@ -4302,28 +3341,34 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
  * used for controlling the debug level.
  *
  * See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
  */
 static ssize_t show_debug_level(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
-       struct iwl_priv *priv = d->driver_data;
-
-       return sprintf(buf, "0x%08X\n", priv->debug_level);
+       struct iwl_priv *priv = dev_get_drvdata(d);
+       return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
 }
 static ssize_t store_debug_level(struct device *d,
                                struct device_attribute *attr,
                                 const char *buf, size_t count)
 {
-       struct iwl_priv *priv = d->driver_data;
+       struct iwl_priv *priv = dev_get_drvdata(d);
        unsigned long val;
        int ret;
 
        ret = strict_strtoul(buf, 0, &val);
        if (ret)
                IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
-       else
+       else {
                priv->debug_level = val;
-
+               if (iwl_alloc_traffic_mem(priv))
+                       IWL_ERR(priv,
+                               "Not enough memory to generate traffic log\n");
+       }
        return strnlen(buf, count);
 }
 
@@ -4335,7 +3380,7 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
 static ssize_t show_temperature(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
-       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+       struct iwl_priv *priv = dev_get_drvdata(d);
 
        if (!iwl_is_alive(priv))
                return -EAGAIN;
@@ -4348,7 +3393,7 @@ static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
 static ssize_t show_tx_power(struct device *d,
                             struct device_attribute *attr, char *buf)
 {
-       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+       struct iwl_priv *priv = dev_get_drvdata(d);
        return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
 }
 
@@ -4356,7 +3401,7 @@ static ssize_t store_tx_power(struct device *d,
                              struct device_attribute *attr,
                              const char *buf, size_t count)
 {
-       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+       struct iwl_priv *priv = dev_get_drvdata(d);
        char *p = (char *)buf;
        u32 val;
 
@@ -4374,7 +3419,7 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
 static ssize_t show_flags(struct device *d,
                          struct device_attribute *attr, char *buf)
 {
-       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+       struct iwl_priv *priv = dev_get_drvdata(d);
 
        return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
 }
@@ -4383,7 +3428,7 @@ static ssize_t store_flags(struct device *d,
                           struct device_attribute *attr,
                           const char *buf, size_t count)
 {
-       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+       struct iwl_priv *priv = dev_get_drvdata(d);
        u32 flags = simple_strtoul(buf, NULL, 0);
 
        mutex_lock(&priv->mutex);
@@ -4395,7 +3440,7 @@ static ssize_t store_flags(struct device *d,
                        IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
                                       flags);
                        priv->staging_rxon.flags = cpu_to_le32(flags);
-                       iwl3945_commit_rxon(priv);
+                       iwlcore_commit_rxon(priv);
                }
        }
        mutex_unlock(&priv->mutex);
@@ -4408,7 +3453,7 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
 static ssize_t show_filter_flags(struct device *d,
                                 struct device_attribute *attr, char *buf)
 {
-       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+       struct iwl_priv *priv = dev_get_drvdata(d);
 
        return sprintf(buf, "0x%04X\n",
                le32_to_cpu(priv->active_rxon.filter_flags));
@@ -4418,7 +3463,7 @@ static ssize_t store_filter_flags(struct device *d,
                                  struct device_attribute *attr,
                                  const char *buf, size_t count)
 {
-       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+       struct iwl_priv *priv = dev_get_drvdata(d);
        u32 filter_flags = simple_strtoul(buf, NULL, 0);
 
        mutex_lock(&priv->mutex);
@@ -4431,7 +3476,7 @@ static ssize_t store_filter_flags(struct device *d,
                                       "0x%04X\n", filter_flags);
                        priv->staging_rxon.filter_flags =
                                cpu_to_le32(filter_flags);
-                       iwl3945_commit_rxon(priv);
+                       iwlcore_commit_rxon(priv);
                }
        }
        mutex_unlock(&priv->mutex);
@@ -4539,87 +3584,6 @@ static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
                   store_retry_rate);
 
 
-static ssize_t store_power_level(struct device *d,
-                                struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       int ret;
-       unsigned long mode;
-
-
-       mutex_lock(&priv->mutex);
-
-       if (!iwl_is_ready(priv)) {
-               ret = -EAGAIN;
-               goto out;
-       }
-
-       ret = strict_strtoul(buf, 10, &mode);
-       if (ret)
-               goto out;
-
-       ret = iwl_power_set_user_mode(priv, mode);
-       if (ret) {
-               IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n");
-               goto out;
-       }
-       ret = count;
-
- out:
-       mutex_unlock(&priv->mutex);
-       return ret;
-}
-
-static ssize_t show_power_level(struct device *d,
-                               struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       int mode = priv->power_data.user_power_setting;
-       int system = priv->power_data.system_power_setting;
-       int level = priv->power_data.power_mode;
-       char *p = buf;
-
-       switch (system) {
-       case IWL_POWER_SYS_AUTO:
-               p += sprintf(p, "SYSTEM:auto");
-               break;
-       case IWL_POWER_SYS_AC:
-               p += sprintf(p, "SYSTEM:ac");
-               break;
-       case IWL_POWER_SYS_BATTERY:
-               p += sprintf(p, "SYSTEM:battery");
-               break;
-       }
-
-       p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
-                       "fixed" : "auto");
-       p += sprintf(p, "\tINDEX:%d", level);
-       p += sprintf(p, "\n");
-       return p - buf + 1;
-}
-
-static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR,
-                  show_power_level, store_power_level);
-
-#define MAX_WX_STRING 80
-
-/* Values are in microsecond */
-static const s32 timeout_duration[] = {
-       350000,
-       250000,
-       75000,
-       37000,
-       25000,
-};
-static const s32 period_duration[] = {
-       400000,
-       700000,
-       1000000,
-       1000000,
-       1000000
-};
-
 static ssize_t show_channels(struct device *d,
                             struct device_attribute *attr, char *buf)
 {
@@ -4708,7 +3672,7 @@ static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);
 static ssize_t show_status(struct device *d,
                           struct device_attribute *attr, char *buf)
 {
-       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+       struct iwl_priv *priv = dev_get_drvdata(d);
        if (!iwl_is_alive(priv))
                return -EAGAIN;
        return sprintf(buf, "0x%08x\n", (int)priv->status);
@@ -4720,30 +3684,17 @@ static ssize_t dump_error_log(struct device *d,
                              struct device_attribute *attr,
                              const char *buf, size_t count)
 {
+       struct iwl_priv *priv = dev_get_drvdata(d);
        char *p = (char *)buf;
 
        if (p[0] == '1')
-               iwl3945_dump_nic_error_log((struct iwl_priv *)d->driver_data);
+               iwl3945_dump_nic_error_log(priv);
 
        return strnlen(buf, count);
 }
 
 static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
 
-static ssize_t dump_event_log(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       char *p = (char *)buf;
-
-       if (p[0] == '1')
-               iwl3945_dump_nic_event_log((struct iwl_priv *)d->driver_data);
-
-       return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
-
 /*****************************************************************************
  *
  * driver setup and tear down
@@ -4759,7 +3710,6 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
        INIT_WORK(&priv->up, iwl3945_bg_up);
        INIT_WORK(&priv->restart, iwl3945_bg_restart);
        INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
-       INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
        INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
        INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
        INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
@@ -4789,13 +3739,11 @@ static struct attribute *iwl3945_sysfs_entries[] = {
        &dev_attr_antenna.attr,
        &dev_attr_channels.attr,
        &dev_attr_dump_errors.attr,
-       &dev_attr_dump_events.attr,
        &dev_attr_flags.attr,
        &dev_attr_filter_flags.attr,
 #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
        &dev_attr_measurement.attr,
 #endif
-       &dev_attr_power_level.attr,
        &dev_attr_retry_rate.attr,
        &dev_attr_statistics.attr,
        &dev_attr_status.attr,
@@ -4816,16 +3764,15 @@ static struct ieee80211_ops iwl3945_hw_ops = {
        .tx = iwl3945_mac_tx,
        .start = iwl3945_mac_start,
        .stop = iwl3945_mac_stop,
-       .add_interface = iwl3945_mac_add_interface,
-       .remove_interface = iwl3945_mac_remove_interface,
-       .config = iwl3945_mac_config,
-       .config_interface = iwl3945_mac_config_interface,
+       .add_interface = iwl_mac_add_interface,
+       .remove_interface = iwl_mac_remove_interface,
+       .config = iwl_mac_config,
        .configure_filter = iwl_configure_filter,
        .set_key = iwl3945_mac_set_key,
-       .get_tx_stats = iwl3945_mac_get_tx_stats,
-       .conf_tx = iwl3945_mac_conf_tx,
-       .reset_tsf = iwl3945_mac_reset_tsf,
-       .bss_info_changed = iwl3945_bss_info_changed,
+       .get_tx_stats = iwl_mac_get_tx_stats,
+       .conf_tx = iwl_mac_conf_tx,
+       .reset_tsf = iwl_mac_reset_tsf,
+       .bss_info_changed = iwl_bss_info_changed,
        .hw_scan = iwl_mac_hw_scan
 };
 
@@ -4838,7 +3785,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
        priv->ibss_beacon = NULL;
 
        spin_lock_init(&priv->lock);
-       spin_lock_init(&priv->power_data.lock);
        spin_lock_init(&priv->sta_lock);
        spin_lock_init(&priv->hcmd_lock);
 
@@ -4847,7 +3793,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
        mutex_init(&priv->mutex);
 
        /* Clear the driver's (not device's) station table */
-       iwl3945_clear_stations_table(priv);
+       iwl_clear_stations_table(priv);
 
        priv->data_retry_limit = -1;
        priv->ieee_channels = NULL;
@@ -4862,8 +3808,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
        priv->qos_data.qos_cap.val = 0;
 
        priv->rates_mask = IWL_RATES_MASK;
-       /* If power management is turned on, default to CAM mode */
-       priv->power_mode = IWL_POWER_MODE_CAM;
        priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
 
        if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
@@ -4909,7 +3853,10 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
 
        /* Tell mac80211 our characteristics */
        hw->flags = IEEE80211_HW_SIGNAL_DBM |
-                   IEEE80211_HW_NOISE_DBM;
+                   IEEE80211_HW_NOISE_DBM |
+                   IEEE80211_HW_SPECTRUM_MGMT |
+                   IEEE80211_HW_SUPPORTS_PS |
+                   IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
        hw->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_STATION) |
@@ -4917,11 +3864,16 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
 
        hw->wiphy->custom_regulatory = true;
 
+       /* Firmware does not support this */
+       hw->wiphy->disable_beacon_hints = true;
+
+       hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
+       /* we create the 802.11 header and a zero-length SSID element */
+       hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
+
        /* Default value; 4 EDCA QOS priorities */
        hw->queues = 4;
 
-       hw->conf.beacon_int = 100;
-
        if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
                priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
                        &priv->bands[IEEE80211_BAND_2GHZ];
@@ -4964,15 +3916,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        priv = hw->priv;
        SET_IEEE80211_DEV(hw, &pdev->dev);
 
-       if ((iwl3945_mod_params.num_of_queues > IWL39_MAX_NUM_QUEUES) ||
-            (iwl3945_mod_params.num_of_queues < IWL_MIN_NUM_QUEUES)) {
-               IWL_ERR(priv,
-                       "invalid queues_num, should be between %d and %d\n",
-                       IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
-               err = -EINVAL;
-               goto out_ieee80211_free_hw;
-       }
-
        /*
         * Disabling hardware scan means that mac80211 will perform scans
         * "the hard way", rather than using device's scan.
@@ -4986,11 +3929,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
        priv->cfg = cfg;
        priv->pci_dev = pdev;
+       priv->inta_mask = CSR_INI_SET_MASK;
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-       priv->debug_level = iwl3945_mod_params.debug;
        atomic_set(&priv->restrict_refcnt, 0);
 #endif
+       if (iwl_alloc_traffic_mem(priv))
+               IWL_ERR(priv, "Not enough memory to generate traffic log\n");
 
        /***************************
         * 2. Initializing PCI bus
@@ -5002,9 +3947,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        pci_set_master(pdev);
 
-       err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
        if (!err)
-               err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
        if (err) {
                IWL_WARN(priv, "No suitable DMA available.\n");
                goto out_pci_disable_device;
@@ -5032,6 +3977,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
         * PCI Tx retries from interfering with C3 CPU state */
        pci_write_config_byte(pdev, 0x41, 0x00);
 
+       /* this spin lock will be used in apm_ops.init and EEPROM access
+        * we should init now
+        */
+       spin_lock_init(&priv->reg_lock);
+
        /* amp init */
        err = priv->cfg->ops->lib->apm_ops.init(priv);
        if (err < 0) {
@@ -5077,20 +4027,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n",
                priv->cfg->name);
 
-       /***********************************
-        * 7. Initialize Module Parameters
-        * **********************************/
-
-       /* Initialize module parameter values here */
-       /* Disable radio (SW RF KILL) via parameter when loading driver */
-       if (iwl3945_mod_params.disable) {
-               set_bit(STATUS_RF_KILL_SW, &priv->status);
-               IWL_DEBUG_INFO(priv, "Radio disabled.\n");
-       }
-
-
        /***********************
-        * 8. Setup Services
+        * 7. Setup Services
         * ********************/
 
        spin_lock_irqsave(&priv->lock, flags);
@@ -5099,8 +4037,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        pci_enable_msi(priv->pci_dev);
 
-       err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED,
-                         DRV_NAME, priv);
+       err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
+                         IRQF_SHARED, DRV_NAME, priv);
        if (err) {
                IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
                goto out_disable_msi;
@@ -5118,7 +4056,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        iwl3945_setup_rx_handlers(priv);
 
        /*********************************
-        * 9. Setup and Register mac80211
+        * 8. Setup and Register mac80211
         * *******************************/
 
        iwl_enable_interrupts(priv);
@@ -5127,12 +4065,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        if (err)
                goto  out_remove_sysfs;
 
-       err = iwl_rfkill_init(priv);
+       err = iwl_dbgfs_register(priv, DRV_NAME);
        if (err)
-               IWL_ERR(priv, "Unable to initialize RFKILL system. "
-                                 "Ignoring error: %d\n", err);
-       else
-               iwl_rfkill_set_hw_state(priv);
+               IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
        /* Start monitoring the killswitch */
        queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
@@ -5163,6 +4098,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        pci_disable_device(pdev);
  out_ieee80211_free_hw:
        ieee80211_free_hw(priv->hw);
+       iwl_free_traffic_mem(priv);
  out:
        return err;
 }
@@ -5177,6 +4113,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
        IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
+       iwl_dbgfs_unregister(priv);
+
        set_bit(STATUS_EXIT_PENDING, &priv->status);
 
        if (priv->mac80211_registered) {
@@ -5197,17 +4135,16 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
        sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
-       iwl_rfkill_unregister(priv);
-       cancel_delayed_work(&priv->rfkill_poll);
+       cancel_delayed_work_sync(&priv->rfkill_poll);
 
        iwl3945_dealloc_ucode_pci(priv);
 
        if (priv->rxq.bd)
-               iwl_rx_queue_free(priv, &priv->rxq);
+               iwl3945_rx_queue_free(priv, &priv->rxq);
        iwl3945_hw_txq_ctx_free(priv);
 
        iwl3945_unset_hw_params(priv);
-       iwl3945_clear_stations_table(priv);
+       iwl_clear_stations_table(priv);
 
        /*netif_stop_queue(dev); */
        flush_workqueue(priv->workqueue);
@@ -5217,6 +4154,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
         * until now... */
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
+       iwl_free_traffic_mem(priv);
 
        free_irq(pdev->irq, priv);
        pci_disable_msi(pdev);
@@ -5235,43 +4173,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
        ieee80211_free_hw(priv->hw);
 }
 
-#ifdef CONFIG_PM
-
-static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-
-       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 int iwl3945_pci_resume(struct pci_dev *pdev)
-{
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-       int ret;
-
-       pci_set_power_state(pdev, PCI_D0);
-       ret = pci_enable_device(pdev);
-       if (ret)
-               return ret;
-       pci_restore_state(pdev);
-
-       if (priv->is_open)
-               iwl3945_mac_start(priv->hw);
-
-       clear_bit(STATUS_IN_SUSPEND, &priv->status);
-       return 0;
-}
-
-#endif /* CONFIG_PM */
 
 /*****************************************************************************
  *
@@ -5285,8 +4186,8 @@ static struct pci_driver iwl3945_driver = {
        .probe = iwl3945_pci_probe,
        .remove = __devexit_p(iwl3945_pci_remove),
 #ifdef CONFIG_PM
-       .suspend = iwl3945_pci_suspend,
-       .resume = iwl3945_pci_resume,
+       .suspend = iwl_pci_suspend,
+       .resume = iwl_pci_resume,
 #endif
 };
 
@@ -5327,19 +4228,15 @@ MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
 
 module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444);
 MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(disable, iwl3945_mod_params.disable, int, 0444);
-MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
 module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444);
 MODULE_PARM_DESC(swcrypto,
                 "using software crypto (default 1 [software])\n");
-module_param_named(debug, iwl3945_mod_params.debug, uint, 0444);
+#ifdef CONFIG_IWLWIFI_DEBUG
+module_param_named(debug, iwl_debug_level, uint, 0644);
 MODULE_PARM_DESC(debug, "debug output mask");
+#endif
 module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444);
 MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
-
-module_param_named(queues_num, iwl3945_mod_params.num_of_queues, int, 0444);
-MODULE_PARM_DESC(queues_num, "number of hw queues.");
-
 module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444);
 MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error");