iwlwifi: change email contact information
[safe/jmp/linux-2.6] / drivers / net / wireless / iwlwifi / iwl3945-base.c
index d4daa04..278f4a8 100644 (file)
  * file called LICENSE.
  *
  * Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ *  Intel Linux Wireless <ilw@linux.intel.com>
  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  *
  *****************************************************************************/
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
@@ -42,6 +41,7 @@
 #include <linux/if_arp.h>
 
 #include <net/ieee80211_radiotap.h>
+#include <net/lib80211.h>
 #include <net/mac80211.h>
 
 #include <asm/div64.h>
@@ -70,7 +70,7 @@ static int iwl3945_param_disable;  /* def: 0 = enable radio */
 static int iwl3945_param_antenna;  /* def: 0 = both antennas (use diversity) */
 int iwl3945_param_hwcrypto;        /* def: 0 = use software encryption */
 static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */
-int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */
+int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
 
 /*
  * module name, copyright, version, etc.
@@ -102,62 +102,12 @@ MODULE_VERSION(DRV_VERSION);
 MODULE_AUTHOR(DRV_COPYRIGHT);
 MODULE_LICENSE("GPL");
 
-static __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
-{
-       u16 fc = le16_to_cpu(hdr->frame_control);
-       int hdr_len = ieee80211_get_hdrlen(fc);
-
-       if ((fc & 0x00cc) == (IEEE80211_STYPE_QOS_DATA | IEEE80211_FTYPE_DATA))
-               return (__le16 *) ((u8 *) hdr + hdr_len - QOS_CONTROL_LEN);
-       return NULL;
-}
-
 static const struct ieee80211_supported_band *iwl3945_get_band(
                struct iwl3945_priv *priv, enum ieee80211_band band)
 {
        return priv->hw->wiphy->bands[band];
 }
 
-static int iwl3945_is_empty_essid(const char *essid, int essid_len)
-{
-       /* Single white space is for Linksys APs */
-       if (essid_len == 1 && essid[0] == ' ')
-               return 1;
-
-       /* Otherwise, if the entire essid is 0, we assume it is hidden */
-       while (essid_len) {
-               essid_len--;
-               if (essid[essid_len] != '\0')
-                       return 0;
-       }
-
-       return 1;
-}
-
-static const char *iwl3945_escape_essid(const char *essid, u8 essid_len)
-{
-       static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-       const char *s = essid;
-       char *d = escaped;
-
-       if (iwl3945_is_empty_essid(essid, essid_len)) {
-               memcpy(escaped, "<hidden>", sizeof("<hidden>"));
-               return escaped;
-       }
-
-       essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
-       while (essid_len--) {
-               if (*s == '\0') {
-                       *d++ = '\\';
-                       *d++ = '0';
-                       s++;
-               } else
-                       *d++ = *s++;
-       }
-       *d = '\0';
-       return escaped;
-}
-
 /*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
  * DMA services
  *
@@ -285,10 +235,8 @@ static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv,
        return 0;
 
  error:
-       if (txq->txb) {
-               kfree(txq->txb);
-               txq->txb = NULL;
-       }
+       kfree(txq->txb);
+       txq->txb = NULL;
 
        return -ENOMEM;
 }
@@ -375,10 +323,8 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t
                                    txq->q.n_bd, txq->bd, txq->q.dma_addr);
 
        /* De-alloc array of per-TFD driver data */
-       if (txq->txb) {
-               kfree(txq->txb);
-               txq->txb = NULL;
-       }
+       kfree(txq->txb);
+       txq->txb = NULL;
 
        /* 0-fill queue descriptor structure */
        memset(txq, 0, sizeof(*txq));
@@ -461,7 +407,6 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
        int index = IWL_INVALID_STATION;
        struct iwl3945_station_entry *station;
        unsigned long flags_spin;
-       DECLARE_MAC_BUF(mac);
        u8 rate;
 
        spin_lock_irqsave(&priv->sta_lock, flags_spin);
@@ -495,7 +440,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
                return index;
        }
 
-       IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr));
+       IWL_DEBUG_ASSOC("Add STA ID %d: %pM\n", index, addr);
        station = &priv->stations[index];
        station->used = 1;
        priv->num_stations++;
@@ -547,10 +492,20 @@ static inline int iwl3945_is_init(struct iwl3945_priv *priv)
        return test_bit(STATUS_INIT, &priv->status);
 }
 
+static inline int iwl3945_is_rfkill_sw(struct iwl3945_priv *priv)
+{
+       return test_bit(STATUS_RF_KILL_SW, &priv->status);
+}
+
+static inline int iwl3945_is_rfkill_hw(struct iwl3945_priv *priv)
+{
+       return test_bit(STATUS_RF_KILL_HW, &priv->status);
+}
+
 static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv)
 {
-       return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
-              test_bit(STATUS_RF_KILL_SW, &priv->status);
+       return iwl3945_is_rfkill_hw(priv) ||
+               iwl3945_is_rfkill_sw(priv);
 }
 
 static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv)
@@ -564,7 +519,7 @@ static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv)
 
 /*************** HOST COMMAND QUEUE FUNCTIONS   *****/
 
-#define IWL_CMD(x) case x : return #x
+#define IWL_CMD(x) case x: return #x
 
 static const char *get_cmd_string(u8 cmd)
 {
@@ -980,7 +935,7 @@ static int iwl3945_full_rxon_required(struct iwl3945_priv *priv)
 {
 
        /* These items are only settable from the full RXON command */
-       if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ||
+       if (!(iwl3945_is_associated(priv)) ||
            compare_ether_addr(priv->staging_rxon.bssid_addr,
                               priv->active_rxon.bssid_addr) ||
            compare_ether_addr(priv->staging_rxon.node_addr,
@@ -1068,7 +1023,6 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
        /* cast away the const for active_rxon in this function */
        struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
        int rc = 0;
-       DECLARE_MAC_BUF(mac);
 
        if (!iwl3945_is_alive(priv))
                return -1;
@@ -1129,11 +1083,11 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
        IWL_DEBUG_INFO("Sending RXON\n"
                       "* with%s RXON_FILTER_ASSOC_MSK\n"
                       "* channel = %d\n"
-                      "* bssid = %s\n",
+                      "* bssid = %pM\n",
                       ((priv->staging_rxon.filter_flags &
                         RXON_FILTER_ASSOC_MSK) ? "" : "out"),
                       le16_to_cpu(priv->staging_rxon.channel),
-                      print_mac(mac, priv->staging_rxon.bssid_addr));
+                      priv->staging_rxon.bssid_addr);
 
        /* Apply the new configuration */
        rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON,
@@ -1165,7 +1119,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
        /* 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 (iwl3945_is_associated(priv) &&
-           (priv->iw_mode == IEEE80211_IF_TYPE_STA))
+           (priv->iw_mode == NL80211_IFTYPE_STATION))
                if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, 1, 0)
                    == IWL_INVALID_STATION) {
                        IWL_ERROR("Error adding AP address for transmit.\n");
@@ -1452,8 +1406,8 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
 {
 
        if (!iwl3945_is_associated(priv) || !priv->ibss_beacon ||
-           ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
-            (priv->iw_mode != IEEE80211_IF_TYPE_AP)))
+           ((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
+            (priv->iw_mode != NL80211_IFTYPE_AP)))
                return 0;
 
        if (priv->ibss_beacon->len > left)
@@ -1464,9 +1418,16 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
        return priv->ibss_beacon->len;
 }
 
-static u8 iwl3945_rate_get_lowest_plcp(int rate_mask)
+static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv)
 {
        u8 i;
+       int rate_mask;
+
+       /* Set rate mask*/
+       if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
+               rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK;
+       else
+               rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK;
 
        for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
             i = iwl3945_rates[i].next_ieee) {
@@ -1474,7 +1435,11 @@ static u8 iwl3945_rate_get_lowest_plcp(int rate_mask)
                        return iwl3945_rates[i].plcp;
        }
 
-       return IWL_RATE_INVALID;
+       /* No valid rate was found. Assign the lowest one */
+       if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
+               return IWL_RATE_1M_PLCP;
+       else
+               return IWL_RATE_6M_PLCP;
 }
 
 static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv)
@@ -1492,16 +1457,7 @@ static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv)
                return -ENOMEM;
        }
 
-       if (!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)) {
-               rate = iwl3945_rate_get_lowest_plcp(priv->active_rate_basic &
-                                               0xFF0);
-               if (rate == IWL_INVALID_RATE)
-                       rate = IWL_RATE_6M_PLCP;
-       } else {
-               rate = iwl3945_rate_get_lowest_plcp(priv->active_rate_basic & 0xF);
-               if (rate == IWL_INVALID_RATE)
-                       rate = IWL_RATE_1M_PLCP;
-       }
+       rate = iwl3945_rate_get_lowest_plcp(priv);
 
        frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
 
@@ -1562,7 +1518,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
        BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
 
        if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
-               IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
+               IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp);
                return -ENOENT;
        }
 
@@ -1587,7 +1543,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
                }
 
                if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
-                       IWL_ERROR("Time out reading EEPROM[%d]", addr);
+                       IWL_ERROR("Time out reading EEPROM[%d]\n", addr);
                        return -ETIMEDOUT;
                }
                e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
@@ -1639,7 +1595,7 @@ static u16 iwl3945_supported_rate_to_ie(u8 *ie, u16 supported_rate,
  */
 static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
                              struct ieee80211_mgmt *frame,
-                             int left, int is_direct)
+                             int left)
 {
        int len = 0;
        u8 *pos = NULL;
@@ -1669,20 +1625,6 @@ static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
        *pos++ = WLAN_EID_SSID;
        *pos++ = 0;
 
-       /* fill in our direct SSID IE... */
-       if (is_direct) {
-               /* ...next IE... */
-               left -= 2 + priv->essid_len;
-               if (left < 0)
-                       return 0;
-               /* ... fill it in... */
-               *pos++ = WLAN_EID_SSID;
-               *pos++ = priv->essid_len;
-               memcpy(pos, priv->essid, priv->essid_len);
-               pos += priv->essid_len;
-               len += 2 + priv->essid_len;
-       }
-
        /* fill in supported rate */
        /* ...next IE... */
        left -= 2;
@@ -1751,14 +1693,14 @@ static void iwl3945_reset_qos(struct iwl3945_priv *priv)
        spin_lock_irqsave(&priv->lock, flags);
        priv->qos_data.qos_active = 0;
 
-       if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
+       if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
                if (priv->qos_data.qos_enable)
                        priv->qos_data.qos_active = 1;
                if (!(priv->active_rate & 0xfff0)) {
                        cw_min = 31;
                        is_legacy = 1;
                }
-       } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+       } else if (priv->iw_mode == NL80211_IFTYPE_AP) {
                if (priv->qos_data.qos_enable)
                        priv->qos_data.qos_active = 1;
        } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
@@ -1851,7 +1793,7 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
        spin_unlock_irqrestore(&priv->lock, flags);
 
        if (force || iwl3945_is_associated(priv)) {
-               IWL_DEBUG_QOS("send QoS cmd with Qos active %d \n",
+               IWL_DEBUG_QOS("send QoS cmd with QoS active %d \n",
                              priv->qos_data.qos_active);
 
                iwl3945_send_qos_params_command(priv,
@@ -1875,7 +1817,7 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
 
 
 /* default power management (not Tx power) table values */
-/* for tim  0-10 */
+/* for TIM  0-10 */
 static struct iwl3945_power_vec_entry range_0[IWL_POWER_AC] = {
        {{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
        {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
@@ -1885,7 +1827,7 @@ static struct iwl3945_power_vec_entry range_0[IWL_POWER_AC] = {
        {{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1}
 };
 
-/* for tim > 10 */
+/* for TIM > 10 */
 static struct iwl3945_power_vec_entry range_1[IWL_POWER_AC] = {
        {{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
        {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500),
@@ -2035,36 +1977,6 @@ static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode)
        return rc;
 }
 
-int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header)
-{
-       /* Filter incoming packets to determine if they are targeted toward
-        * this network, discarding packets coming from ourselves */
-       switch (priv->iw_mode) {
-       case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source    | BSSID */
-               /* packets from our adapter are dropped (echo) */
-               if (!compare_ether_addr(header->addr2, priv->mac_addr))
-                       return 0;
-               /* {broad,multi}cast packets to our IBSS go through */
-               if (is_multicast_ether_addr(header->addr1))
-                       return !compare_ether_addr(header->addr3, priv->bssid);
-               /* packets to our adapter go through */
-               return !compare_ether_addr(header->addr1, priv->mac_addr);
-       case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
-               /* packets from our adapter are dropped (echo) */
-               if (!compare_ether_addr(header->addr3, priv->mac_addr))
-                       return 0;
-               /* {broad,multi}cast packets to our BSS go through */
-               if (is_multicast_ether_addr(header->addr1))
-                       return !compare_ether_addr(header->addr2, priv->bssid);
-               /* packets to our adapter go through */
-               return !compare_ether_addr(header->addr1, priv->mac_addr);
-       default:
-               return 1;
-       }
-
-       return 1;
-}
-
 /**
  * iwl3945_scan_cancel - Cancel any currently executing HW scan
  *
@@ -2117,20 +2029,6 @@ static int iwl3945_scan_cancel_timeout(struct iwl3945_priv *priv, unsigned long
        return ret;
 }
 
-static void iwl3945_sequence_reset(struct iwl3945_priv *priv)
-{
-       /* Reset ieee stats */
-
-       /* We don't reset the net_device_stats (ieee->stats) on
-        * re-association */
-
-       priv->last_seq_num = -1;
-       priv->last_frag_num = -1;
-       priv->last_packet_time = 0;
-
-       iwl3945_scan_cancel(priv);
-}
-
 #define MAX_UCODE_BEACON_INTERVAL      1024
 #define INTEL_CONN_LISTEN_INTERVAL     __constant_cpu_to_le16(0xA)
 
@@ -2169,7 +2067,7 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
        beacon_int = priv->beacon_int;
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
+       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);
@@ -2205,7 +2103,7 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
 
 static int iwl3945_scan_initiate(struct iwl3945_priv *priv)
 {
-       if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+       if (priv->iw_mode == NL80211_IFTYPE_AP) {
                IWL_ERROR("APs don't scan.\n");
                return 0;
        }
@@ -2227,7 +2125,10 @@ static int iwl3945_scan_initiate(struct iwl3945_priv *priv)
        }
 
        IWL_DEBUG_INFO("Starting scan...\n");
-       priv->scan_bands = 2;
+       if (priv->cfg->sku & IWL_SKU_G)
+               priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
+       if (priv->cfg->sku & IWL_SKU_A)
+               priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
        set_bit(STATUS_SCANNING, &priv->status);
        priv->scan_start = jiffies;
        priv->scan_pass_start = priv->scan_start;
@@ -2264,7 +2165,7 @@ static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
                else
                        priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
-               if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+               if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
                        priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
                priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
@@ -2276,36 +2177,37 @@ static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
 /*
  * initialize rxon structure with default values from eeprom
  */
-static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
+static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv,
+                                             int mode)
 {
        const struct iwl3945_channel_info *ch_info;
 
        memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
 
-       switch (priv->iw_mode) {
-       case IEEE80211_IF_TYPE_AP:
+       switch (mode) {
+       case NL80211_IFTYPE_AP:
                priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
                break;
 
-       case IEEE80211_IF_TYPE_STA:
+       case NL80211_IFTYPE_STATION:
                priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
                priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
                break;
 
-       case IEEE80211_IF_TYPE_IBSS:
+       case NL80211_IFTYPE_ADHOC:
                priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
                priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
                priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
                                                  RXON_FILTER_ACCEPT_GRP_MSK;
                break;
 
-       case IEEE80211_IF_TYPE_MNTR:
+       case NL80211_IFTYPE_MONITOR:
                priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
                priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
                    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
                break;
        default:
-               IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
+               IWL_ERROR("Unsupported interface type %d\n", mode);
                break;
        }
 
@@ -2319,7 +2221,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
 #endif
 
        ch_info = iwl3945_get_channel_info(priv, priv->band,
-                                      le16_to_cpu(priv->staging_rxon.channel));
+                                      le16_to_cpu(priv->active_rxon.channel));
 
        if (!ch_info)
                ch_info = &priv->channel_info[0];
@@ -2328,8 +2230,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
         * in some case A channels are all non IBSS
         * in this case force B/G channel
         */
-       if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
-           !(is_channel_ibss(ch_info)))
+       if ((mode == NL80211_IFTYPE_ADHOC) && !(is_channel_ibss(ch_info)))
                ch_info = &priv->channel_info[0];
 
        priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
@@ -2348,7 +2249,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
 
 static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
 {
-       if (mode == IEEE80211_IF_TYPE_IBSS) {
+       if (mode == NL80211_IFTYPE_ADHOC) {
                const struct iwl3945_channel_info *ch_info;
 
                ch_info = iwl3945_get_channel_info(priv,
@@ -2362,14 +2263,12 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
                }
        }
 
-       priv->iw_mode = mode;
-
-       iwl3945_connection_init_rx_config(priv);
+       iwl3945_connection_init_rx_config(priv, mode);
        memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
 
        iwl3945_clear_stations_table(priv);
 
-       /* dont commit rxon if rf-kill is on*/
+       /* don't commit rxon if rf-kill is on*/
        if (!iwl3945_is_ready_rf(priv))
                return -EAGAIN;
 
@@ -2386,18 +2285,19 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
 }
 
 static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
-                                     struct ieee80211_tx_control *ctl,
+                                     struct ieee80211_tx_info *info,
                                      struct iwl3945_cmd *cmd,
                                      struct sk_buff *skb_frag,
                                      int last_frag)
 {
-       struct iwl3945_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo;
+       struct iwl3945_hw_key *keyinfo =
+           &priv->stations[info->control.hw_key->hw_key_idx].keyinfo;
 
        switch (keyinfo->alg) {
        case ALG_CCMP:
                cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
                memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
-               IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
+               IWL_DEBUG_TX("tx_cmd with AES hwcrypto\n");
                break;
 
        case ALG_TKIP:
@@ -2414,7 +2314,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
 
        case ALG_WEP:
                cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP |
-                   (ctl->key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
+                   (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
 
                if (keyinfo->keylen == 13)
                        cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
@@ -2422,7 +2322,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
                memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen);
 
                IWL_DEBUG_TX("Configuring packet for WEP encryption "
-                            "with key %d\n", ctl->key_idx);
+                            "with key %d\n", info->control.hw_key->hw_key_idx);
                break;
 
        default:
@@ -2436,20 +2336,20 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
  */
 static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
                                  struct iwl3945_cmd *cmd,
-                                 struct ieee80211_tx_control *ctrl,
+                                 struct ieee80211_tx_info *info,
                                  struct ieee80211_hdr *hdr,
                                  int is_unicast, u8 std_id)
 {
-       __le16 *qc;
-       u16 fc = le16_to_cpu(hdr->frame_control);
+       __le16 fc = hdr->frame_control;
        __le32 tx_flags = cmd->cmd.tx.tx_flags;
+       u8 rc_flags = info->control.rates[0].flags;
 
        cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-       if (!(ctrl->flags & IEEE80211_TXCTL_NO_ACK)) {
+       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
                tx_flags |= TX_CMD_FLG_ACK_MSK;
-               if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
+               if (ieee80211_is_mgmt(fc))
                        tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-               if (ieee80211_is_probe_response(fc) &&
+               if (ieee80211_is_probe_resp(fc) &&
                    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
                        tx_flags |= TX_CMD_FLG_TSF_MSK;
        } else {
@@ -2458,20 +2358,21 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
        }
 
        cmd->cmd.tx.sta_id = std_id;
-       if (ieee80211_get_morefrag(hdr))
+       if (ieee80211_has_morefrags(fc))
                tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
 
-       qc = ieee80211_get_qos_ctrl(hdr);
-       if (qc) {
-               cmd->cmd.tx.tid_tspec = (u8) (le16_to_cpu(*qc) & 0xf);
+       if (ieee80211_is_data_qos(fc)) {
+               u8 *qc = ieee80211_get_qos_ctl(hdr);
+               cmd->cmd.tx.tid_tspec = qc[0] & 0xf;
                tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
-       } else
+       } else {
                tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+       }
 
-       if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
+       if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
                tx_flags |= TX_CMD_FLG_RTS_MSK;
                tx_flags &= ~TX_CMD_FLG_CTS_MSK;
-       } else if (ctrl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
+       } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
                tx_flags &= ~TX_CMD_FLG_RTS_MSK;
                tx_flags |= TX_CMD_FLG_CTS_MSK;
        }
@@ -2480,9 +2381,8 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
                tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
 
        tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
-       if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
-               if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ ||
-                   (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
+       if (ieee80211_is_mgmt(fc)) {
+               if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
                        cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
                else
                        cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
@@ -2515,11 +2415,11 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
 
        /* If we are a client station in a BSS network, use the special
         * AP station entry (that's the only station we communicate with) */
-       case IEEE80211_IF_TYPE_STA:
+       case NL80211_IFTYPE_STATION:
                return IWL_AP_ID;
 
        /* If we are an AP, then find the station, or use BCAST */
-       case IEEE80211_IF_TYPE_AP:
+       case NL80211_IFTYPE_AP:
                sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
                if (sta_id != IWL_INVALID_STATION)
                        return sta_id;
@@ -2527,9 +2427,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
 
        /* If this frame is going out to an IBSS network, find the station,
         * or create a new station table entry */
-       case IEEE80211_IF_TYPE_IBSS: {
-               DECLARE_MAC_BUF(mac);
-
+       case NL80211_IFTYPE_ADHOC: {
                /* Create new station table entry */
                sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
                if (sta_id != IWL_INVALID_STATION)
@@ -2540,14 +2438,19 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
                if (sta_id != IWL_INVALID_STATION)
                        return sta_id;
 
-               IWL_DEBUG_DROP("Station %s not in station map. "
+               IWL_DEBUG_DROP("Station %pM not in station map. "
                               "Defaulting to broadcast...\n",
-                              print_mac(mac, hdr->addr1));
+                              hdr->addr1);
                iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
                return priv->hw_setting.bcast_sta_id;
        }
+       /* If we are in monitor mode, use BCAST. This is required for
+        * packet injection. */
+       case NL80211_IFTYPE_MONITOR:
+               return priv->hw_setting.bcast_sta_id;
+
        default:
-               IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
+               IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode);
                return priv->hw_setting.bcast_sta_id;
        }
 }
@@ -2555,25 +2458,27 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
 /*
  * start REPLY_TX command process
  */
-static int iwl3945_tx_skb(struct iwl3945_priv *priv,
-                     struct sk_buff *skb, struct ieee80211_tx_control *ctl)
+static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct iwl3945_tfd_frame *tfd;
        u32 *control_flags;
-       int txq_id = ctl->queue;
+       int txq_id = skb_get_queue_mapping(skb);
        struct iwl3945_tx_queue *txq = NULL;
        struct iwl3945_queue *q = NULL;
        dma_addr_t phys_addr;
        dma_addr_t txcmd_phys;
        struct iwl3945_cmd *out_cmd = NULL;
-       u16 len, idx, len_org;
-       u8 id, hdr_len, unicast;
+       u16 len, idx, len_org, hdr_len;
+       u8 id;
+       u8 unicast;
        u8 sta_id;
+       u8 tid = 0;
        u16 seq_number = 0;
-       u16 fc;
-       __le16 *qc;
+       __le16 fc;
        u8 wait_write_ptr = 0;
+       u8 *qc = NULL;
        unsigned long flags;
        int rc;
 
@@ -2583,12 +2488,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
                goto drop_unlock;
        }
 
-       if (!priv->vif) {
-               IWL_DEBUG_DROP("Dropping - !priv->vif\n");
-               goto drop_unlock;
-       }
-
-       if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
+       if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
                IWL_ERROR("ERROR: No TX rate available.\n");
                goto drop_unlock;
        }
@@ -2596,44 +2496,43 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
        unicast = !is_multicast_ether_addr(hdr->addr1);
        id = 0;
 
-       fc = le16_to_cpu(hdr->frame_control);
+       fc = hdr->frame_control;
 
 #ifdef CONFIG_IWL3945_DEBUG
        if (ieee80211_is_auth(fc))
                IWL_DEBUG_TX("Sending AUTH frame\n");
-       else if (ieee80211_is_assoc_request(fc))
+       else if (ieee80211_is_assoc_req(fc))
                IWL_DEBUG_TX("Sending ASSOC frame\n");
-       else if (ieee80211_is_reassoc_request(fc))
+       else if (ieee80211_is_reassoc_req(fc))
                IWL_DEBUG_TX("Sending REASSOC frame\n");
 #endif
 
        /* drop all data frame if we are not associated */
-       if ((!iwl3945_is_associated(priv) ||
-            ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id)) &&
-           ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
+       if (ieee80211_is_data(fc) &&
+           (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */
+           (!iwl3945_is_associated(priv) ||
+            ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
                IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n");
                goto drop_unlock;
        }
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       hdr_len = ieee80211_get_hdrlen(fc);
+       hdr_len = ieee80211_hdrlen(fc);
 
        /* Find (or create) index into station table for destination station */
        sta_id = iwl3945_get_sta_id(priv, hdr);
        if (sta_id == IWL_INVALID_STATION) {
-               DECLARE_MAC_BUF(mac);
-
-               IWL_DEBUG_DROP("Dropping - INVALID STATION: %s\n",
-                              print_mac(mac, hdr->addr1));
+               IWL_DEBUG_DROP("Dropping - INVALID STATION: %pM\n",
+                              hdr->addr1);
                goto drop;
        }
 
        IWL_DEBUG_RATE("station Id %d\n", sta_id);
 
-       qc = ieee80211_get_qos_ctrl(hdr);
-       if (qc) {
-               u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
+       if (ieee80211_is_data_qos(fc)) {
+               qc = ieee80211_get_qos_ctl(hdr);
+               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
                seq_number = priv->stations[sta_id].tid[tid].seq_number &
                                IEEE80211_SCTL_SEQ;
                hdr->seq_ctrl = cpu_to_le16(seq_number) |
@@ -2657,8 +2556,6 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
        /* Set up driver data for this TFD */
        memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl3945_tx_info));
        txq->txb[q->write_ptr].skb[0] = skb;
-       memcpy(&(txq->txb[q->write_ptr].status.control),
-              ctl, sizeof(struct ieee80211_tx_control));
 
        /* Init first empty entry in queue's array of Tx/cmd buffers */
        out_cmd = &txq->cmd[idx];
@@ -2707,8 +2604,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
         * first entry */
        iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
 
-       if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
-               iwl3945_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
+       if (info->control.hw_key)
+               iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, 0);
 
        /* Set up TFD's 2nd entry to point directly to remainder of skb,
         * if any (802.11 null frames have no payload). */
@@ -2733,20 +2630,18 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
        out_cmd->cmd.tx.len = cpu_to_le16(len);
 
        /* TODO need this for burst mode later on */
-       iwl3945_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id);
+       iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, unicast, sta_id);
 
        /* set is_hcca to 0; it probably will never be implemented */
-       iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
+       iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
 
        out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
        out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
 
-       if (!ieee80211_get_morefrag(hdr)) {
+       if (!ieee80211_has_morefrags(hdr->frame_control)) {
                txq->need_update = 1;
-               if (qc) {
-                       u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
+               if (qc)
                        priv->stations[sta_id].tid[tid].seq_number = seq_number;
-               }
        } else {
                wait_write_ptr = 1;
                txq->need_update = 0;
@@ -2756,7 +2651,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
                           sizeof(out_cmd->cmd.tx));
 
        iwl3945_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
-                          ieee80211_get_hdrlen(fc));
+                          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);
@@ -2775,7 +2670,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
                        spin_unlock_irqrestore(&priv->lock, flags);
                }
 
-               ieee80211_stop_queue(priv->hw, ctl->queue);
+               ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb));
        }
 
        return 0;
@@ -2853,7 +2748,7 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio)
        if (disable_radio) {
                iwl3945_scan_cancel(priv);
                /* FIXME: This is a workaround for AP */
-               if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+               if (priv->iw_mode != NL80211_IFTYPE_AP) {
                        spin_lock_irqsave(&priv->lock, flags);
                        iwl3945_write32(priv, CSR_UCODE_DRV_GP1_SET,
                                    CSR_UCODE_SW_BIT_RFKILL);
@@ -2885,7 +2780,8 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio)
                return;
        }
 
-       queue_work(priv->workqueue, &priv->restart);
+       if (priv->is_open)
+               queue_work(priv->workqueue, &priv->restart);
        return;
 }
 
@@ -2921,72 +2817,6 @@ void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb,
        }
 }
 
-#define IWL_PACKET_RETRY_TIME HZ
-
-int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header)
-{
-       u16 sc = le16_to_cpu(header->seq_ctrl);
-       u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
-       u16 frag = sc & IEEE80211_SCTL_FRAG;
-       u16 *last_seq, *last_frag;
-       unsigned long *last_time;
-
-       switch (priv->iw_mode) {
-       case IEEE80211_IF_TYPE_IBSS:{
-               struct list_head *p;
-               struct iwl3945_ibss_seq *entry = NULL;
-               u8 *mac = header->addr2;
-               int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
-
-               __list_for_each(p, &priv->ibss_mac_hash[index]) {
-                       entry = list_entry(p, struct iwl3945_ibss_seq, list);
-                       if (!compare_ether_addr(entry->mac, mac))
-                               break;
-               }
-               if (p == &priv->ibss_mac_hash[index]) {
-                       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
-                       if (!entry) {
-                               IWL_ERROR("Cannot malloc new mac entry\n");
-                               return 0;
-                       }
-                       memcpy(entry->mac, mac, ETH_ALEN);
-                       entry->seq_num = seq;
-                       entry->frag_num = frag;
-                       entry->packet_time = jiffies;
-                       list_add(&entry->list, &priv->ibss_mac_hash[index]);
-                       return 0;
-               }
-               last_seq = &entry->seq_num;
-               last_frag = &entry->frag_num;
-               last_time = &entry->packet_time;
-               break;
-       }
-       case IEEE80211_IF_TYPE_STA:
-               last_seq = &priv->last_seq_num;
-               last_frag = &priv->last_frag_num;
-               last_time = &priv->last_packet_time;
-               break;
-       default:
-               return 0;
-       }
-       if ((*last_seq == seq) &&
-           time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) {
-               if (*last_frag == frag)
-                       goto drop;
-               if (*last_frag + 1 != frag)
-                       /* out-of-order fragment */
-                       goto drop;
-       } else
-               *last_seq = seq;
-
-       *last_frag = frag;
-       *last_time = jiffies;
-       return 0;
-
- drop:
-       return 1;
-}
-
 #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
 
 #include "iwl-spectrum.h"
@@ -3238,7 +3068,7 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
        struct sk_buff *beacon;
 
        /* Pull updated AP beacon from mac80211. will fail if not in AP mode */
-       beacon = ieee80211_beacon_get(priv->hw, priv->vif, NULL);
+       beacon = ieee80211_beacon_get(priv->hw, priv->vif);
 
        if (!beacon) {
                IWL_ERROR("update beacon failed\n");
@@ -3273,7 +3103,7 @@ static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv,
                le32_to_cpu(beacon->low_tsf), rate);
 #endif
 
-       if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
+       if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
            (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
                queue_work(priv->workqueue, &priv->beacon_update);
 }
@@ -3352,13 +3182,18 @@ static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv,
        cancel_delayed_work(&priv->scan_check);
 
        IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n",
-                      (priv->scan_bands == 2) ? "2.4" : "5.2",
+                      (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ?
+                                                       "2.4" : "5.2",
                       jiffies_to_msecs(elapsed_jiffies
                                        (priv->scan_pass_start, jiffies)));
 
-       /* Remove this scanned band from the list
-        * of pending bands to scan */
-       priv->scan_bands--;
+       /* Remove this scanned band from the list of pending
+        * bands to scan, band G precedes A in order of scanning
+        * as seen in iwl3945_bg_request_scan */
+       if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ))
+               priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ);
+       else if (priv->scan_bands &  BIT(IEEE80211_BAND_5GHZ))
+               priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ);
 
        /* If a request to abort was given, or the scan did not succeed
         * then we reset the scan state machine and terminate,
@@ -3914,7 +3749,7 @@ int iwl3945_calc_db_from_ratio(int sig_ratio)
        /* 100:1 or higher, divide by 10 and use table,
         *   add 20 dB to make up for divide by 10 */
        if (sig_ratio >= 100)
-               return (20 + (int)ratio2dB[sig_ratio/10]);
+               return 20 + (int)ratio2dB[sig_ratio/10];
 
        /* We shouldn't see this */
        if (sig_ratio < 1)
@@ -4126,8 +3961,6 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv,
 #ifdef CONFIG_IWL3945_DEBUG
 static void iwl3945_print_rx_config_cmd(struct iwl3945_rxon_cmd *rxon)
 {
-       DECLARE_MAC_BUF(mac);
-
        IWL_DEBUG_RADIO("RX CONFIG:\n");
        iwl3945_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
        IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
@@ -4138,10 +3971,8 @@ static void iwl3945_print_rx_config_cmd(struct iwl3945_rxon_cmd *rxon)
        IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n",
                        rxon->ofdm_basic_rates);
        IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
-       IWL_DEBUG_RADIO("u8[6] node_addr: %s\n",
-                       print_mac(mac, rxon->node_addr));
-       IWL_DEBUG_RADIO("u8[6] bssid_addr: %s\n",
-                       print_mac(mac, rxon->bssid_addr));
+       IWL_DEBUG_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr);
+       IWL_DEBUG_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
        IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
 }
 #endif
@@ -4157,7 +3988,7 @@ static void iwl3945_enable_interrupts(struct iwl3945_priv *priv)
 /* call this function to flush any scheduled tasklet */
 static inline void iwl_synchronize_irq(struct iwl3945_priv *priv)
 {
-       /* wait to make sure we flush pedding tasklet*/
+       /* wait to make sure we flush pending tasklet*/
        synchronize_irq(priv->pci_dev->irq);
        tasklet_kill(&priv->irq_tasklet);
 }
@@ -4480,35 +4311,6 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
        /* Safely ignore these bits for debug checks below */
        inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
 
-       /* HW RF KILL switch toggled (4965 only) */
-       if (inta & CSR_INT_BIT_RF_KILL) {
-               int hw_rf_kill = 0;
-               if (!(iwl3945_read32(priv, CSR_GP_CNTRL) &
-                               CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
-                       hw_rf_kill = 1;
-
-               IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL | IWL_DL_ISR,
-                               "RF_KILL bit toggled to %s.\n",
-                               hw_rf_kill ? "disable radio":"enable radio");
-
-               /* Queue restart only if RF_KILL switch was set to "kill"
-                *   when we loaded driver, and is now set to "enable".
-                * After we're Alive, RF_KILL gets handled by
-                *   iwl3945_rx_card_state_notif() */
-               if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
-                       clear_bit(STATUS_RF_KILL_HW, &priv->status);
-                       queue_work(priv->workqueue, &priv->restart);
-               }
-
-               handled |= CSR_INT_BIT_RF_KILL;
-       }
-
-       /* Chip got too hot and stopped itself (4965 only) */
-       if (inta & CSR_INT_BIT_CT_KILL) {
-               IWL_ERROR("Microcode CT kill error detected.\n");
-               handled |= CSR_INT_BIT_CT_KILL;
-       }
-
        /* Error detected by uCode */
        if (inta & CSR_INT_BIT_SW_ERR) {
                IWL_ERROR("Microcode SW error detected.  Restarting 0x%X.\n",
@@ -4609,7 +4411,7 @@ static irqreturn_t iwl3945_isr(int irq, void *data)
 
        if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
                /* Hardware disappeared */
-               IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
+               IWL_WARNING("HARDWARE GONE?? INTA == 0x%08x\n", inta);
                goto unplugged;
        }
 
@@ -4840,7 +4642,7 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
                        ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
                        ch_info->min_power = 0;
 
-                       IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x"
+                       IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
                                       " %ddBm): Ad-Hoc %ssupported\n",
                                       ch_info->channel,
                                       is_channel_a_band(ch_info) ?
@@ -4850,7 +4652,6 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
                                       CHECK_AND_PRINT(ACTIVE),
                                       CHECK_AND_PRINT(RADAR),
                                       CHECK_AND_PRINT(WIDE),
-                                      CHECK_AND_PRINT(NARROW),
                                       CHECK_AND_PRINT(DFS),
                                       eeprom_ch_info[ch].flags,
                                       eeprom_ch_info[ch].max_power_avg,
@@ -4890,8 +4691,11 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
 /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
  * sending probe req.  This should be set long enough to hear probe responses
  * from more than one AP.  */
-#define IWL_ACTIVE_DWELL_TIME_24    (20)       /* all times in msec */
-#define IWL_ACTIVE_DWELL_TIME_52    (10)
+#define IWL_ACTIVE_DWELL_TIME_24    (30)       /* all times in msec */
+#define IWL_ACTIVE_DWELL_TIME_52    (20)
+
+#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3)
+#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2)
 
 /* For faster active scanning, scan will move to the next channel if fewer than
  * PLCP_QUIET_THRESH packets are heard on this channel within
@@ -4900,7 +4704,7 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
  * no other traffic).
  * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
 #define IWL_PLCP_QUIET_THRESH       __constant_cpu_to_le16(1)  /* packets */
-#define IWL_ACTIVE_QUIET_TIME       __constant_cpu_to_le16(5)  /* msec */
+#define IWL_ACTIVE_QUIET_TIME       __constant_cpu_to_le16(10) /* msec */
 
 /* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
  * Must be set longer than active dwell time.
@@ -4910,19 +4714,23 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
 #define IWL_PASSIVE_DWELL_BASE      (100)
 #define IWL_CHANNEL_TUNE_TIME       5
 
+#define IWL_SCAN_PROBE_MASK(n)  (BIT(n) | (BIT(n) - BIT(1)))
+
 static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv,
-                                               enum ieee80211_band band)
+                                               enum ieee80211_band band,
+                                               u8 n_probes)
 {
        if (band == IEEE80211_BAND_5GHZ)
-               return IWL_ACTIVE_DWELL_TIME_52;
+               return IWL_ACTIVE_DWELL_TIME_52 +
+                       IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1);
        else
-               return IWL_ACTIVE_DWELL_TIME_24;
+               return IWL_ACTIVE_DWELL_TIME_24 +
+                       IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
 }
 
 static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv,
                                          enum ieee80211_band band)
 {
-       u16 active = iwl3945_get_active_dwell_time(priv, band);
        u16 passive = (band == IEEE80211_BAND_2GHZ) ?
            IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
            IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
@@ -4937,15 +4745,12 @@ static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv,
                passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
        }
 
-       if (passive <= active)
-               passive = active + 1;
-
        return passive;
 }
 
 static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
                                         enum ieee80211_band band,
-                                    u8 is_active, u8 direct_mask,
+                                    u8 is_active, u8 n_probes,
                                     struct iwl3945_scan_channel *scan_ch)
 {
        const struct ieee80211_channel *channels = NULL;
@@ -4961,44 +4766,52 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
 
        channels = sband->channels;
 
-       active_dwell = iwl3945_get_active_dwell_time(priv, band);
+       active_dwell = iwl3945_get_active_dwell_time(priv, band, n_probes);
        passive_dwell = iwl3945_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].hw_value ==
-                   le16_to_cpu(priv->active_rxon.channel)) {
-                       if (iwl3945_is_associated(priv)) {
-                               IWL_DEBUG_SCAN
-                                   ("Skipping current channel %d\n",
-                                    le16_to_cpu(priv->active_rxon.channel));
-                               continue;
-                       }
-               } else if (priv->only_active_channel)
+               if (channels[i].flags & IEEE80211_CHAN_DISABLED)
                        continue;
 
                scan_ch->channel = channels[i].hw_value;
 
                ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel);
                if (!is_channel_valid(ch_info)) {
-                       IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
+                       IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n",
                                       scan_ch->channel);
                        continue;
                }
 
+               scan_ch->active_dwell = cpu_to_le16(active_dwell);
+               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+               /* If passive , set up for auto-switch
+                *  and use long active_dwell time.
+                */
                if (!is_active || is_channel_passive(ch_info) ||
-                   (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
+                   (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
                        scan_ch->type = 0;      /* passive */
-               else
+                       if (IWL_UCODE_API(priv->ucode_ver) == 1)
+                               scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
+               } else {
                        scan_ch->type = 1;      /* active */
+               }
 
-               if (scan_ch->type & 1)
-                       scan_ch->type |= (direct_mask << 1);
-
-               if (is_channel_narrow(ch_info))
-                       scan_ch->type |= (1 << 7);
-
-               scan_ch->active_dwell = cpu_to_le16(active_dwell);
-               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+               /* Set direct probe bits. These may be used both for active
+                * scan channels (probes gets sent right away),
+                * or for passive channels (probes get se sent only after
+                * hearing clear Rx packet).*/
+               if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
+                       if (n_probes)
+                               scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+               } else {
+                       /* uCode v1 does not allow setting direct probe bits on
+                        * passive channel. */
+                       if ((scan_ch->type & 1) && n_probes)
+                               scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+               }
 
                /* Set txpower levels to defaults */
                scan_ch->tpc.dsp_atten = 110;
@@ -5201,7 +5014,7 @@ static void iwl3945_dealloc_ucode_pci(struct iwl3945_priv *priv)
  * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host,
  *     looking at all data.
  */
-static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 * image, u32 len)
+static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 *image, u32 len)
 {
        u32 val;
        u32 save_len = len;
@@ -5350,7 +5163,7 @@ static int iwl3945_verify_bsm(struct iwl3945_priv *priv)
        val = iwl3945_read_prph(priv, BSM_WR_DWCOUNT_REG);
        for (reg = BSM_SRAM_LOWER_BOUND;
             reg < BSM_SRAM_LOWER_BOUND + len;
-            reg += sizeof(u32), image ++) {
+            reg += sizeof(u32), image++) {
                val = iwl3945_read_prph(priv, reg);
                if (val != le32_to_cpu(*image)) {
                        IWL_ERROR("BSM uCode verification failed at "
@@ -5499,25 +5312,41 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv)
 static int iwl3945_read_ucode(struct iwl3945_priv *priv)
 {
        struct iwl3945_ucode *ucode;
-       int ret = 0;
+       int ret = -EINVAL, index;
        const struct firmware *ucode_raw;
        /* firmware file name contains uCode/driver compatibility version */
-       const char *name = priv->cfg->fw_name;
+       const char *name_pre = priv->cfg->fw_name_pre;
+       const unsigned int api_max = priv->cfg->ucode_api_max;
+       const unsigned int api_min = priv->cfg->ucode_api_min;
+       char buf[25];
        u8 *src;
        size_t len;
-       u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
+       u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
 
        /* Ask kernel firmware_class module to get the boot firmware off disk.
         * request_firmware() is synchronous, file is in memory on return. */
-       ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
-       if (ret < 0) {
-               IWL_ERROR("%s firmware file req failed: Reason %d\n",
-                               name, ret);
-               goto error;
+       for (index = api_max; index >= api_min; index--) {
+               sprintf(buf, "%s%u%s", name_pre, index, ".ucode");
+               ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
+               if (ret < 0) {
+                       IWL_ERROR("%s firmware file req failed: Reason %d\n",
+                                 buf, ret);
+                       if (ret == -ENOENT)
+                               continue;
+                       else
+                               goto error;
+               } else {
+                       if (index < api_max)
+                               IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n",
+                                         buf, api_max);
+                       IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
+                                      buf, ucode_raw->size);
+                       break;
+               }
        }
 
-       IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
-                      name, ucode_raw->size);
+       if (ret < 0)
+               goto error;
 
        /* Make sure that we got at least our header! */
        if (ucode_raw->size < sizeof(*ucode)) {
@@ -5529,20 +5358,46 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
        /* Data from ucode file:  header followed by uCode images */
        ucode = (void *)ucode_raw->data;
 
-       ver = le32_to_cpu(ucode->ver);
+       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);
 
-       IWL_DEBUG_INFO("f/w package hdr ucode version = 0x%x\n", 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 */
+
+       if (api_ver < api_min || api_ver > api_max) {
+               IWL_ERROR("Driver unable to support your firmware API. "
+                         "Driver supports v%u, firmware is v%u.\n",
+                         api_max, api_ver);
+               priv->ucode_ver = 0;
+               ret = -EINVAL;
+               goto err_release;
+       }
+       if (api_ver != api_max)
+               IWL_ERROR("Firmware has old API version. Expected %u, "
+                         "got %u. New firmware can be obtained "
+                         "from http://www.intellinuxwireless.org.\n",
+                         api_max, api_ver);
+
+       printk(KERN_INFO DRV_NAME " loaded firmware version %u.%u.%u.%u\n",
+                      IWL_UCODE_MAJOR(priv->ucode_ver),
+                      IWL_UCODE_MINOR(priv->ucode_ver),
+                      IWL_UCODE_API(priv->ucode_ver),
+                      IWL_UCODE_SERIAL(priv->ucode_ver));
+       IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n",
+                      priv->ucode_ver);
        IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", inst_size);
        IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n", data_size);
        IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n", init_size);
        IWL_DEBUG_INFO("f/w package hdr init data size = %u\n", init_data_size);
        IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n", boot_size);
 
+
        /* Verify size of file vs. image size info in file's header */
        if (ucode_raw->size < sizeof(*ucode) +
                inst_size + data_size + init_size +
@@ -5719,7 +5574,7 @@ static int iwl3945_set_ucode_ptrs(struct iwl3945_priv *priv)
        iwl3945_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
                                 priv->ucode_data.len);
 
-       /* Inst bytecount must be last to set up, bit 31 signals uCode
+       /* Inst byte count must be last to set up, bit 31 signals uCode
         *   that all new ptr/size info is in place */
        iwl3945_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
                                 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
@@ -5777,6 +5632,10 @@ static void iwl3945_init_alive_start(struct iwl3945_priv *priv)
 }
 
 
+/* 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
@@ -5811,7 +5670,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
 
        rc = iwl3945_grab_nic_access(priv);
        if (rc) {
-               IWL_WARNING("Can not read rfkill status from adapter\n");
+               IWL_WARNING("Can not read RFKILL status from adapter\n");
                return;
        }
 
@@ -5821,7 +5680,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
 
        if (rfkill & 0x1) {
                clear_bit(STATUS_RF_KILL_HW, &priv->status);
-               /* if rfkill is not on, then wait for thermal
+               /* if RFKILL is not on, then wait for thermal
                 * sensor in adapter to kick in */
                while (iwl3945_hw_get_temperature(priv) == 0) {
                        thermal_spin++;
@@ -5843,7 +5702,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
        if (iwl3945_is_rfkill(priv))
                return;
 
-       ieee80211_start_queues(priv->hw);
+       ieee80211_wake_queues(priv->hw);
 
        priv->active_rate = priv->rates_mask;
        priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
@@ -5859,7 +5718,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
                active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
        } else {
                /* Initialize our rx_config data */
-               iwl3945_connection_init_rx_config(priv);
+               iwl3945_connection_init_rx_config(priv, priv->iw_mode);
                memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
        }
 
@@ -5869,9 +5728,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
        /* Configure the adapter for unassociated operation */
        iwl3945_commit_rxon(priv);
 
-       /* At this point, the NIC is initialized and operational */
-       priv->notif_missed_beacons = 0;
-
        iwl3945_reg_txpower_periodic(priv);
 
        iwl3945_led_register(priv);
@@ -5883,6 +5739,14 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
        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);
+       }
+
        return;
 
  restart:
@@ -5937,7 +5801,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
                               test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
                                        STATUS_GEO_CONFIGURED |
                               test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-                                       STATUS_IN_SUSPEND;
+                                       STATUS_IN_SUSPEND |
+                               test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+                                       STATUS_EXIT_PENDING;
                goto exit;
        }
 
@@ -5952,7 +5818,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
                        test_bit(STATUS_IN_SUSPEND, &priv->status) <<
                                STATUS_IN_SUSPEND |
                        test_bit(STATUS_FW_ERROR, &priv->status) <<
-                               STATUS_FW_ERROR;
+                               STATUS_FW_ERROR |
+                       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+                               STATUS_EXIT_PENDING;
 
        spin_lock_irqsave(&priv->lock, flags);
        iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
@@ -6013,7 +5881,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
        }
 
        if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
-               IWL_ERROR("ucode not available for device bringup\n");
+               IWL_ERROR("ucode not available for device bring up\n");
                return -EIO;
        }
 
@@ -6084,6 +5952,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
 
        set_bit(STATUS_EXIT_PENDING, &priv->status);
        __iwl3945_down(priv);
+       clear_bit(STATUS_EXIT_PENDING, &priv->status);
 
        /* tried to restart and config the device for as long as our
         * patience could withstand */
@@ -6151,7 +6020,9 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
                                    "Kill switch must be turned off for "
                                    "wireless networking to work.\n");
        }
+
        mutex_unlock(&priv->mutex);
+       iwl3945_rfkill_set_hw_state(priv);
 }
 
 #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
@@ -6189,8 +6060,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        int rc = 0;
        struct iwl3945_scan_cmd *scan;
        struct ieee80211_conf *conf = NULL;
-       u8 direct_mask;
+       u8 n_probes = 2;
        enum ieee80211_band band;
+       DECLARE_SSID_BUF(ssid);
 
        conf = ieee80211_get_hw_conf(priv->hw);
 
@@ -6201,7 +6073,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                goto done;
        }
 
-       /* Make sure the scan wasn't cancelled before this queued work
+       /* Make sure the scan wasn't canceled before this queued work
         * was given the chance to run... */
        if (!test_bit(STATUS_SCANNING, &priv->status))
                goto done;
@@ -6291,47 +6163,37 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        if (priv->one_direct_scan) {
                IWL_DEBUG_SCAN
                    ("Kicking off one direct scan for '%s'\n",
-                    iwl3945_escape_essid(priv->direct_ssid,
-                                     priv->direct_ssid_len));
+                    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);
-               direct_mask = 1;
-       } else if (!iwl3945_is_associated(priv) && priv->essid_len) {
-               scan->direct_scan[0].id = WLAN_EID_SSID;
-               scan->direct_scan[0].len = priv->essid_len;
-               memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
-               direct_mask = 1;
+               n_probes++;
        } else
-               direct_mask = 0;
+               IWL_DEBUG_SCAN("Kicking off one indirect 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 */
        scan->tx_cmd.len = cpu_to_le16(
                iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
-                       IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
+                       IWL_MAX_SCAN_SIZE - sizeof(*scan)));
        scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
        scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
        scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
 
        /* flags + rate selection */
 
-       switch (priv->scan_bands) {
-       case 2:
+       if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
                scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
                scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
                scan->good_CRC_th = 0;
                band = IEEE80211_BAND_2GHZ;
-               break;
-
-       case 1:
+       } 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;
                band = IEEE80211_BAND_5GHZ;
-               break;
-
-       default:
+       } else {
                IWL_WARNING("Invalid scan band count\n");
                goto done;
        }
@@ -6339,25 +6201,17 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        /* select Rx antennas */
        scan->flags |= iwl3945_get_antenna_flags(priv);
 
-       if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
+       if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
                scan->filter_flags = RXON_FILTER_PROMISC_MSK;
 
-       if (direct_mask) {
-               IWL_DEBUG_SCAN
-                   ("Initiating direct scan for %s.\n",
-                    iwl3945_escape_essid(priv->essid, priv->essid_len));
-               scan->channel_count =
-                       iwl3945_get_channels_for_scan(
-                               priv, band, 1, /* active */
-                               direct_mask,
-                               (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
-       } else {
-               IWL_DEBUG_SCAN("Initiating indirect scan.\n");
-               scan->channel_count =
-                       iwl3945_get_channels_for_scan(
-                               priv, band, 0, /* passive */
-                               direct_mask,
-                               (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
+       scan->channel_count =
+               iwl3945_get_channels_for_scan(priv, band, 1, /* active */
+                                             n_probes,
+                       (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
+
+       if (scan->channel_count == 0) {
+               IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count);
+               goto done;
        }
 
        cmd.len += le16_to_cpu(scan->tx_cmd.len) +
@@ -6377,6 +6231,14 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        return;
 
  done:
+       /* can not perform scan make sure we clear scanning
+        * bits from status so next scan request can be performed.
+        * if we dont clear scanning status bit here all next scan
+        * will fail
+       */
+       clear_bit(STATUS_SCAN_HW, &priv->status);
+       clear_bit(STATUS_SCANNING, &priv->status);
+
        /* inform mac80211 scan aborted */
        queue_work(priv->workqueue, &priv->scan_completed);
        mutex_unlock(&priv->mutex);
@@ -6392,6 +6254,7 @@ static void iwl3945_bg_up(struct work_struct *data)
        mutex_lock(&priv->mutex);
        __iwl3945_up(priv);
        mutex_unlock(&priv->mutex);
+       iwl3945_rfkill_set_hw_state(priv);
 }
 
 static void iwl3945_bg_restart(struct work_struct *data)
@@ -6420,34 +6283,26 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
 
 #define IWL_DELAY_NEXT_SCAN (HZ*2)
 
-static void iwl3945_bg_post_associate(struct work_struct *data)
+static void iwl3945_post_associate(struct iwl3945_priv *priv)
 {
-       struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv,
-                                            post_associate.work);
-
        int rc = 0;
        struct ieee80211_conf *conf = NULL;
-       DECLARE_MAC_BUF(mac);
 
-       if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
-               IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__);
+       if (priv->iw_mode == NL80211_IFTYPE_AP) {
+               IWL_ERROR("%s Should not be called in AP mode\n", __func__);
                return;
        }
 
 
-       IWL_DEBUG_ASSOC("Associated as %d to: %s\n",
-                       priv->assoc_id,
-                       print_mac(mac, priv->active_rxon.bssid_addr));
+       IWL_DEBUG_ASSOC("Associated as %d to: %pM\n",
+                       priv->assoc_id, priv->active_rxon.bssid_addr);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       mutex_lock(&priv->mutex);
-
-       if (!priv->vif || !priv->is_open) {
-               mutex_unlock(&priv->mutex);
+       if (!priv->vif || !priv->is_open)
                return;
-       }
+
        iwl3945_scan_cancel_timeout(priv, 200);
 
        conf = ieee80211_get_hw_conf(priv->hw);
@@ -6481,7 +6336,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
                else
                        priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
-               if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+               if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
                        priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
        }
@@ -6489,16 +6344,13 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
        iwl3945_commit_rxon(priv);
 
        switch (priv->iw_mode) {
-       case IEEE80211_IF_TYPE_STA:
+       case NL80211_IFTYPE_STATION:
                iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
                break;
 
-       case IEEE80211_IF_TYPE_IBSS:
-
-               /* clear out the station table */
-               iwl3945_clear_stations_table(priv);
+       case NL80211_IFTYPE_ADHOC:
 
-               iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
+               priv->assoc_id = 1;
                iwl3945_add_station(priv, priv->bssid, 0, 0);
                iwl3945_sync_sta(priv, IWL_STA_ID,
                                 (priv->band == IEEE80211_BAND_5GHZ) ?
@@ -6511,17 +6363,14 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
 
        default:
                 IWL_ERROR("%s Should not be called in %d mode\n",
-                          __FUNCTION__, priv->iw_mode);
+                          __func__, priv->iw_mode);
                break;
        }
 
-       iwl3945_sequence_reset(priv);
-
        iwl3945_activate_qos(priv, 0);
 
        /* we have just associated, don't start scan too early */
        priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
-       mutex_unlock(&priv->mutex);
 }
 
 static void iwl3945_bg_abort_scan(struct work_struct *work)
@@ -6539,7 +6388,7 @@ static void iwl3945_bg_abort_scan(struct work_struct *work)
        mutex_unlock(&priv->mutex);
 }
 
-static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
 
 static void iwl3945_bg_scan_completed(struct work_struct *work)
 {
@@ -6552,7 +6401,7 @@ static void iwl3945_bg_scan_completed(struct work_struct *work)
                return;
 
        if (test_bit(STATUS_CONF_PENDING, &priv->status))
-               iwl3945_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw));
+               iwl3945_mac_config(priv->hw, 0);
 
        ieee80211_scan_completed(priv->hw);
 
@@ -6612,6 +6461,8 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
 
        mutex_unlock(&priv->mutex);
 
+       iwl3945_rfkill_set_hw_state(priv);
+
        if (ret)
                goto out_release_irq;
 
@@ -6667,7 +6518,6 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
                 */
                mutex_lock(&priv->mutex);
                iwl3945_scan_cancel_timeout(priv, 100);
-               cancel_delayed_work(&priv->post_associate);
                mutex_unlock(&priv->mutex);
        }
 
@@ -6682,22 +6532,16 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
        IWL_DEBUG_MAC80211("leave\n");
 }
 
-static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
-                     struct ieee80211_tx_control *ctl)
+static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct iwl3945_priv *priv = hw->priv;
 
        IWL_DEBUG_MAC80211("enter\n");
 
-       if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
-               IWL_DEBUG_MAC80211("leave - monitor\n");
-               return -1;
-       }
-
        IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-                    ctl->tx_rate->bitrate);
+                    ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
 
-       if (iwl3945_tx_skb(priv, skb, ctl))
+       if (iwl3945_tx_skb(priv, skb))
                dev_kfree_skb_any(skb);
 
        IWL_DEBUG_MAC80211("leave\n");
@@ -6709,7 +6553,6 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
 {
        struct iwl3945_priv *priv = hw->priv;
        unsigned long flags;
-       DECLARE_MAC_BUF(mac);
 
        IWL_DEBUG_MAC80211("enter: type %d\n", conf->type);
 
@@ -6720,13 +6563,14 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
 
        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("Set: %s\n", print_mac(mac, conf->mac_addr));
+               IWL_DEBUG_MAC80211("Set: %pM\n", conf->mac_addr);
                memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
        }
 
@@ -6746,18 +6590,17 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
  * 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, struct ieee80211_conf *conf)
+static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
 {
        struct iwl3945_priv *priv = hw->priv;
        const struct iwl3945_channel_info *ch_info;
+       struct ieee80211_conf *conf = &hw->conf;
        unsigned long flags;
        int ret = 0;
 
        mutex_lock(&priv->mutex);
        IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
 
-       priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
-
        if (!iwl3945_is_ready(priv)) {
                IWL_DEBUG_MAC80211("leave - not ready\n");
                ret = -EIO;
@@ -6777,7 +6620,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
        ch_info = iwl3945_get_channel_info(priv, conf->channel->band,
                                           conf->channel->hw_value);
        if (!is_channel_valid(ch_info)) {
-               IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
+               IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this band.\n",
                               conf->channel->hw_value, conf->channel->band);
                IWL_DEBUG_MAC80211("leave - invalid channel\n");
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -6840,7 +6683,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
                return;
 
        /* The following should be done only at AP bring up */
-       if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) {
+       if (!(iwl3945_is_associated(priv))) {
 
                /* RXON - unassoc (to set timing command) */
                priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
@@ -6873,7 +6716,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
                                priv->staging_rxon.flags &=
                                        ~RXON_FLG_SHORT_SLOT_MSK;
 
-                       if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+                       if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
                                priv->staging_rxon.flags &=
                                        ~RXON_FLG_SHORT_SLOT_MSK;
                }
@@ -6894,8 +6737,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
                                    struct ieee80211_if_conf *conf)
 {
        struct iwl3945_priv *priv = hw->priv;
-       DECLARE_MAC_BUF(mac);
-       unsigned long flags;
        int rc;
 
        if (conf == NULL)
@@ -6903,17 +6744,20 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
 
        if (priv->vif != vif) {
                IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
-               mutex_unlock(&priv->mutex);
                return 0;
        }
 
-       /* XXX: this MUST use conf->mac_addr */
-
-       if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
-           (!conf->beacon || !conf->ssid_len)) {
-               IWL_DEBUG_MAC80211
-                   ("Leaving in AP mode because HostAPD is not ready.\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 (!iwl3945_is_alive(priv))
@@ -6922,8 +6766,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
        mutex_lock(&priv->mutex);
 
        if (conf->bssid)
-               IWL_DEBUG_MAC80211("bssid: %s\n",
-                                  print_mac(mac, conf->bssid));
+               IWL_DEBUG_MAC80211("bssid: %pM\n", conf->bssid);
 
 /*
  * very dubious code was here; the probe filtering flag is never set:
@@ -6932,17 +6775,17 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
            !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
  */
 
-       if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+       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("bssid was set to: %s\n",
-                                          print_mac(mac, conf->bssid));
+                       IWL_DEBUG_MAC80211("bssid was set to: %pM\n",
+                                          conf->bssid);
                }
                if (priv->ibss_beacon)
                        dev_kfree_skb(priv->ibss_beacon);
 
-               priv->ibss_beacon = conf->beacon;
+               priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
        }
 
        if (iwl3945_is_rfkill(priv))
@@ -6967,11 +6810,11 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
                 * to verify) - jpk */
                memcpy(priv->bssid, conf->bssid, ETH_ALEN);
 
-               if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+               if (priv->iw_mode == NL80211_IFTYPE_AP)
                        iwl3945_config_ap(priv);
                else {
                        rc = iwl3945_commit_rxon(priv);
-                       if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
+                       if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
                                iwl3945_add_station(priv,
                                        priv->active_rxon.bssid_addr, 1, 0);
                }
@@ -6983,15 +6826,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
        }
 
  done:
-       spin_lock_irqsave(&priv->lock, flags);
-       if (!conf->ssid_len)
-               memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
-       else
-               memcpy(priv->essid, conf->ssid, conf->ssid_len);
-
-       priv->essid_len = conf->ssid_len;
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        IWL_DEBUG_MAC80211("leave\n");
        mutex_unlock(&priv->mutex);
 
@@ -7003,11 +6837,45 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
                                 unsigned int *total_flags,
                                 int mc_count, struct dev_addr_list *mc_list)
 {
-       /*
-        * XXX: dummy
-        * see also iwl3945_connection_init_rx_config
+       struct iwl3945_priv *priv = hw->priv;
+       __le32 *filter_flags = &priv->staging_rxon.filter_flags;
+
+       IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n",
+                       changed_flags, *total_flags);
+
+       if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) {
+               if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))
+                       *filter_flags |= RXON_FILTER_PROMISC_MSK;
+               else
+                       *filter_flags &= ~RXON_FILTER_PROMISC_MSK;
+       }
+       if (changed_flags & FIF_ALLMULTI) {
+               if (*total_flags & FIF_ALLMULTI)
+                       *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK;
+               else
+                       *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK;
+       }
+       if (changed_flags & FIF_CONTROL) {
+               if (*total_flags & FIF_CONTROL)
+                       *filter_flags |= RXON_FILTER_CTL2HOST_MSK;
+               else
+                       *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK;
+       }
+       if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
+               if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
+                       *filter_flags |= RXON_FILTER_BCON_AWARE_MSK;
+               else
+                       *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK;
+       }
+
+       /* We avoid iwl_commit_rxon here to commit the new filter flags
+        * since mac80211 will call ieee80211_hw_config immediately.
+        * (mc_list is not supported at this time). Otherwise, we need to
+        * queue a background iwl_commit_rxon work.
         */
-       *total_flags = 0;
+
+       *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
+                       FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
 }
 
 static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
@@ -7021,26 +6889,81 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
 
        if (iwl3945_is_ready_rf(priv)) {
                iwl3945_scan_cancel_timeout(priv, 100);
-               cancel_delayed_work(&priv->post_associate);
                priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
                iwl3945_commit_rxon(priv);
        }
        if (priv->vif == conf->vif) {
                priv->vif = NULL;
                memset(priv->bssid, 0, ETH_ALEN);
-               memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
-               priv->essid_len = 0;
        }
        mutex_unlock(&priv->mutex);
 
        IWL_DEBUG_MAC80211("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 iwl3945_priv *priv = hw->priv;
+
+       IWL_DEBUG_MAC80211("changes = 0x%X\n", changes);
+
+       if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+               IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n",
+                                  bss_conf->use_short_preamble);
+               if (bss_conf->use_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("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 (changes & BSS_CHANGED_ASSOC) {
+               IWL_DEBUG_MAC80211("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->timestamp0 = bss_conf->timestamp & 0xFFFFFFFF;
+                       priv->timestamp1 = (bss_conf->timestamp >> 32) &
+                                            0xFFFFFFFF;
+                       priv->assoc_capability = bss_conf->assoc_capability;
+                       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("DISASSOC %d\n", bss_conf->assoc);
+               }
+       } else if (changes && iwl3945_is_associated(priv) && priv->assoc_id) {
+                       IWL_DEBUG_MAC80211("Associated Changes %d\n", changes);
+                       iwl3945_send_rxon_assoc(priv);
+       }
+
+}
+
 static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
 {
        int rc = 0;
        unsigned long flags;
        struct iwl3945_priv *priv = hw->priv;
+       DECLARE_SSID_BUF(ssid_buf);
 
        IWL_DEBUG_MAC80211("enter\n");
 
@@ -7053,7 +6976,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
                goto out_unlock;
        }
 
-       if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {    /* APs don't scan */
+       if (priv->iw_mode == NL80211_IFTYPE_AP) {       /* APs don't scan */
                rc = -EIO;
                IWL_ERROR("ERROR: APs don't scan\n");
                goto out_unlock;
@@ -7065,15 +6988,16 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
                rc = -EAGAIN;
                goto out_unlock;
        }
-       /* if we just finished scan ask for delay */
-       if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies +
-                               IWL_DELAY_NEXT_SCAN, jiffies)) {
+       /* if we just finished scan ask for delay for a broadcast scan */
+       if ((len == 0) && priv->last_scan_jiffies &&
+           time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
+                      jiffies)) {
                rc = -EAGAIN;
                goto out_unlock;
        }
        if (len) {
                IWL_DEBUG_SCAN("direct scan for %s [%d]\n ",
-                              iwl3945_escape_essid(ssid, len), (int)len);
+                              print_ssid(ssid_buf, ssid, len), (int)len);
 
                priv->one_direct_scan = 1;
                priv->direct_ssid_len = (u8)
@@ -7114,10 +7038,8 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
        sta_id = iwl3945_hw_find_station(priv, addr);
        if (sta_id == IWL_INVALID_STATION) {
-               DECLARE_MAC_BUF(mac);
-
-               IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
-                                  print_mac(mac, addr));
+               IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
+                                  addr);
                return -EINVAL;
        }
 
@@ -7154,7 +7076,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        return rc;
 }
 
-static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
                           const struct ieee80211_tx_queue_params *params)
 {
        struct iwl3945_priv *priv = hw->priv;
@@ -7194,7 +7116,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
        spin_unlock_irqrestore(&priv->lock, flags);
 
        mutex_lock(&priv->mutex);
-       if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+       if (priv->iw_mode == NL80211_IFTYPE_AP)
                iwl3945_activate_qos(priv, 1);
        else if (priv->assoc_id && iwl3945_is_associated(priv))
                iwl3945_activate_qos(priv, 0);
@@ -7228,9 +7150,9 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw,
                q = &txq->q;
                avail = iwl3945_queue_space(q);
 
-               stats->data[i].len = q->n_window - avail;
-               stats->data[i].limit = q->n_window - q->high_mark;
-               stats->data[i].count = q->n_window;
+               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);
@@ -7249,14 +7171,6 @@ static int iwl3945_mac_get_stats(struct ieee80211_hw *hw,
        return 0;
 }
 
-static u64 iwl3945_mac_get_tsf(struct ieee80211_hw *hw)
-{
-       IWL_DEBUG_MAC80211("enter\n");
-       IWL_DEBUG_MAC80211("leave\n");
-
-       return 0;
-}
-
 static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
 {
        struct iwl3945_priv *priv = hw->priv;
@@ -7267,8 +7181,6 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
 
        iwl3945_reset_qos(priv);
 
-       cancel_delayed_work(&priv->post_associate);
-
        spin_lock_irqsave(&priv->lock, flags);
        priv->assoc_id = 0;
        priv->assoc_capability = 0;
@@ -7283,7 +7195,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
        priv->beacon_int = priv->hw->conf.beacon_int;
        priv->timestamp1 = 0;
        priv->timestamp0 = 0;
-       if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
+       if ((priv->iw_mode == NL80211_IFTYPE_STATION))
                priv->beacon_int = 0;
 
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -7297,22 +7209,20 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
        /* we are restarting association process
         * clear RXON_FILTER_ASSOC_MSK bit
        */
-       if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+       if (priv->iw_mode != NL80211_IFTYPE_AP) {
                iwl3945_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 != IEEE80211_IF_TYPE_IBSS) {
+       if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
 
                IWL_DEBUG_MAC80211("leave - not in IBSS\n");
                mutex_unlock(&priv->mutex);
                return;
        }
 
-       priv->only_active_channel = 0;
-
        iwl3945_set_rate(priv);
 
        mutex_unlock(&priv->mutex);
@@ -7321,24 +7231,20 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
 
 }
 
-static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-                                struct ieee80211_tx_control *control)
+static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct iwl3945_priv *priv = hw->priv;
        unsigned long flags;
 
-       mutex_lock(&priv->mutex);
        IWL_DEBUG_MAC80211("enter\n");
 
        if (!iwl3945_is_ready_rf(priv)) {
                IWL_DEBUG_MAC80211("leave - RF not ready\n");
-               mutex_unlock(&priv->mutex);
                return -EIO;
        }
 
-       if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
+       if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
                IWL_DEBUG_MAC80211("leave - not IBSS\n");
-               mutex_unlock(&priv->mutex);
                return -EIO;
        }
 
@@ -7356,9 +7262,8 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
 
        iwl3945_reset_qos(priv);
 
-       queue_work(priv->workqueue, &priv->post_associate.work);
+       iwl3945_post_associate(priv);
 
-       mutex_unlock(&priv->mutex);
 
        return 0;
 }
@@ -7404,37 +7309,6 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
 
 #endif /* CONFIG_IWL3945_DEBUG */
 
-static ssize_t show_rf_kill(struct device *d,
-                           struct device_attribute *attr, char *buf)
-{
-       /*
-        * 0 - RF kill not enabled
-        * 1 - SW based RF kill active (sysfs)
-        * 2 - HW based RF kill active
-        * 3 - Both HW and SW based RF kill active
-        */
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-       int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
-                 (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
-
-       return sprintf(buf, "%i\n", val);
-}
-
-static ssize_t store_rf_kill(struct device *d,
-                            struct device_attribute *attr,
-                            const char *buf, size_t count)
-{
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-
-       mutex_lock(&priv->mutex);
-       iwl3945_radio_kill_sw(priv, buf[0] == '1');
-       mutex_unlock(&priv->mutex);
-
-       return count;
-}
-
-static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
-
 static ssize_t show_temperature(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
@@ -7448,15 +7322,6 @@ static ssize_t show_temperature(struct device *d,
 
 static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
 
-static ssize_t show_rs_window(struct device *d,
-                             struct device_attribute *attr,
-                             char *buf)
-{
-       struct iwl3945_priv *priv = d->driver_data;
-       return iwl3945_fill_rs_info(priv->hw, buf, IWL_AP_ID);
-}
-static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
-
 static ssize_t show_tx_power(struct device *d,
                             struct device_attribute *attr, char *buf)
 {
@@ -7563,7 +7428,7 @@ static ssize_t show_measurement(struct device *d,
        struct iwl3945_priv *priv = dev_get_drvdata(d);
        struct iwl3945_spectrum_notification measure_report;
        u32 size = sizeof(measure_report), len = 0, ofs = 0;
-       u8 *data = (u8 *) & measure_report;
+       u8 *data = (u8 *)&measure_report;
        unsigned long flags;
 
        spin_lock_irqsave(&priv->lock, flags);
@@ -7734,7 +7599,7 @@ static ssize_t show_power_level(struct device *d,
        else
                p += sprintf(p, " \n");
 
-       return (p - buf + 1);
+       return p - buf + 1;
 
 }
 
@@ -7756,7 +7621,7 @@ static ssize_t show_statistics(struct device *d,
        struct iwl3945_priv *priv = dev_get_drvdata(d);
        u32 size = sizeof(struct iwl3945_notif_statistics);
        u32 len = 0, ofs = 0;
-       u8 *data = (u8 *) & priv->statistics;
+       u8 *data = (u8 *)&priv->statistics;
        int rc = 0;
 
        if (!iwl3945_is_alive(priv))
@@ -7867,7 +7732,7 @@ static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
 
 /*****************************************************************************
  *
- * driver setup and teardown
+ * driver setup and tear down
  *
  *****************************************************************************/
 
@@ -7885,7 +7750,6 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv)
        INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan);
        INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill);
        INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
-       INIT_DELAYED_WORK(&priv->post_associate, iwl3945_bg_post_associate);
        INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
        INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
        INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check);
@@ -7903,7 +7767,6 @@ static void iwl3945_cancel_deferred_work(struct iwl3945_priv *priv)
        cancel_delayed_work_sync(&priv->init_alive_start);
        cancel_delayed_work(&priv->scan_check);
        cancel_delayed_work(&priv->alive_start);
-       cancel_delayed_work(&priv->post_associate);
        cancel_work_sync(&priv->beacon_update);
 }
 
@@ -7919,8 +7782,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
 #endif
        &dev_attr_power_level.attr,
        &dev_attr_retry_rate.attr,
-       &dev_attr_rf_kill.attr,
-       &dev_attr_rs_window.attr,
        &dev_attr_statistics.attr,
        &dev_attr_status.attr,
        &dev_attr_temperature.attr,
@@ -7947,9 +7808,8 @@ static struct ieee80211_ops iwl3945_hw_ops = {
        .get_stats = iwl3945_mac_get_stats,
        .get_tx_stats = iwl3945_mac_get_tx_stats,
        .conf_tx = iwl3945_mac_conf_tx,
-       .get_tsf = iwl3945_mac_get_tsf,
        .reset_tsf = iwl3945_mac_reset_tsf,
-       .beacon_update = iwl3945_mac_beacon_update,
+       .bss_info_changed = iwl3945_bss_info_changed,
        .hw_scan = iwl3945_mac_hw_scan
 };
 
@@ -7959,9 +7819,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        struct iwl3945_priv *priv;
        struct ieee80211_hw *hw;
        struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data);
-       int i;
        unsigned long flags;
-       DECLARE_MAC_BUF(mac);
+
+       /***********************
+        * 1. Allocating HW data
+        * ********************/
 
        /* Disabling hardware scan means that mac80211 will perform scans
         * "the hard way", rather than using device's scan. */
@@ -7970,10 +7832,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
                iwl3945_hw_ops.hw_scan = NULL;
        }
 
-       if ((iwl3945_param_queues_num > IWL_MAX_NUM_QUEUES) ||
+       if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) ||
            (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) {
                IWL_ERROR("invalid queues_num, should be between %d and %d\n",
-                         IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
+                         IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
                err = -EINVAL;
                goto out;
        }
@@ -7986,53 +7848,41 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
                err = -ENOMEM;
                goto out;
        }
-       SET_IEEE80211_DEV(hw, &pdev->dev);
 
-       hw->rate_control_algorithm = "iwl-3945-rs";
+       SET_IEEE80211_DEV(hw, &pdev->dev);
 
-       IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
        priv = hw->priv;
        priv->hw = hw;
-
        priv->pci_dev = pdev;
        priv->cfg = cfg;
 
+       IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
+       hw->rate_control_algorithm = "iwl-3945-rs";
+       hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
+
        /* Select antenna (may be helpful if only one antenna is connected) */
        priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna;
 #ifdef CONFIG_IWL3945_DEBUG
        iwl3945_debug_level = iwl3945_param_debug;
        atomic_set(&priv->restrict_refcnt, 0);
 #endif
-       priv->retry_rate = 1;
 
-       priv->ibss_beacon = NULL;
+       /* Tell mac80211 our characteristics */
+       hw->flags = IEEE80211_HW_SIGNAL_DBM |
+                   IEEE80211_HW_NOISE_DBM;
 
-       /* Tell mac80211 and its clients (e.g. Wireless Extensions)
-        *   the range of signal quality values that we'll provide.
-        * Negative values for level/noise indicate that we'll provide dBm.
-        * For WE, at least, non-0 values here *enable* display of values
-        *   in app (iwconfig). */
-       hw->max_rssi = -20;     /* signal level, negative indicates dBm */
-       hw->max_noise = -20;    /* noise level, negative indicates dBm */
-       hw->max_signal = 100;   /* link quality indication (%) */
+       hw->wiphy->interface_modes =
+               BIT(NL80211_IFTYPE_STATION) |
+               BIT(NL80211_IFTYPE_ADHOC);
 
-       /* Tell mac80211 our Tx characteristics */
-       hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+       hw->wiphy->fw_handles_regulatory = true;
 
        /* 4 EDCA QOS priorities */
        hw->queues = 4;
 
-       spin_lock_init(&priv->lock);
-       spin_lock_init(&priv->power_data.lock);
-       spin_lock_init(&priv->sta_lock);
-       spin_lock_init(&priv->hcmd_lock);
-
-       for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
-               INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
-
-       INIT_LIST_HEAD(&priv->free_frames);
-
-       mutex_init(&priv->mutex);
+       /***************************
+        * 2. Initializing PCI bus
+        * *************************/
        if (pci_enable_device(pdev)) {
                err = -ENODEV;
                goto out_ieee80211_free_hw;
@@ -8040,14 +7890,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        pci_set_master(pdev);
 
-       /* Clear the driver's (not device's) station table */
-       iwl3945_clear_stations_table(priv);
-
-       priv->data_retry_limit = -1;
-       priv->ieee_channels = NULL;
-       priv->ieee_rates = NULL;
-       priv->band = IEEE80211_BAND_2GHZ;
-
        err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
        if (!err)
                err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
@@ -8061,10 +7903,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        if (err)
                goto out_pci_disable_device;
 
-       /* We disable the RETRY_TIMEOUT register (0x41) to keep
-        * PCI Tx retries from interfering with C3 CPU state */
-       pci_write_config_byte(pdev, 0x41, 0x00);
-
+       /***********************
+        * 3. Read REV Register
+        * ********************/
        priv->hw_base = pci_iomap(pdev, 0, 0);
        if (!priv->hw_base) {
                err = -ENODEV;
@@ -8075,25 +7916,69 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
                        (unsigned long long) pci_resource_len(pdev, 0));
        IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);
 
-       /* Initialize module parameter values here */
+       /* We disable the RETRY_TIMEOUT register (0x41) to keep
+        * PCI Tx retries from interfering with C3 CPU state */
+       pci_write_config_byte(pdev, 0x41, 0x00);
 
-       /* Disable radio (SW RF KILL) via parameter when loading driver */
-       if (iwl3945_param_disable) {
-               set_bit(STATUS_RF_KILL_SW, &priv->status);
-               IWL_DEBUG_INFO("Radio disabled.\n");
-       }
+       /* nic init */
+       iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+                       CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
 
-       priv->iw_mode = IEEE80211_IF_TYPE_STA;
+       iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+       err = iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL,
+                               CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+       if (err < 0) {
+               IWL_DEBUG_INFO("Failed to init the card\n");
+               goto out_remove_sysfs;
+       }
 
-       printk(KERN_INFO DRV_NAME
-               ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
+       /***********************
+        * 4. Read EEPROM
+        * ********************/
+       /* Read the EEPROM */
+       err = iwl3945_eeprom_init(priv);
+       if (err) {
+               IWL_ERROR("Unable to init EEPROM\n");
+               goto out_remove_sysfs;
+       }
+       /* MAC Address location in EEPROM same for 3945/4965 */
+       get_eeprom_mac(priv, priv->mac_addr);
+       IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr);
+       SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 
+       /***********************
+        * 5. Setup HW Constants
+        * ********************/
        /* Device-specific setup */
        if (iwl3945_hw_set_hw_setting(priv)) {
                IWL_ERROR("failed to set hw settings\n");
                goto out_iounmap;
        }
 
+       /***********************
+        * 6. Setup priv
+        * ********************/
+       priv->retry_rate = 1;
+       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);
+
+       INIT_LIST_HEAD(&priv->free_frames);
+       mutex_init(&priv->mutex);
+
+       /* Clear the driver's (not device's) station table */
+       iwl3945_clear_stations_table(priv);
+
+       priv->data_retry_limit = -1;
+       priv->ieee_channels = NULL;
+       priv->ieee_rates = NULL;
+       priv->band = IEEE80211_BAND_2GHZ;
+
+       priv->iw_mode = NL80211_IFTYPE_STATION;
+
        if (iwl3945_param_qos_enable)
                priv->qos_data.qos_enable = 1;
 
@@ -8102,79 +7987,91 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        priv->qos_data.qos_active = 0;
        priv->qos_data.qos_cap.val = 0;
 
-       iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
-       iwl3945_setup_deferred_work(priv);
-       iwl3945_setup_rx_handlers(priv);
 
        priv->rates_mask = IWL_RATES_MASK;
        /* If power management is turned on, default to AC mode */
        priv->power_mode = IWL_POWER_AC;
        priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
 
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl3945_disable_interrupts(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+       err = iwl3945_init_channel_map(priv);
        if (err) {
-               IWL_ERROR("failed to create sysfs device attributes\n");
+               IWL_ERROR("initializing regulatory failed: %d\n", err);
                goto out_release_irq;
        }
 
-       /* nic init */
-       iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
-                    CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
-
-        iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-        err = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
-                          CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
-                          CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
-        if (err < 0) {
-                IWL_DEBUG_INFO("Failed to init the card\n");
-               goto out_remove_sysfs;
-        }
-       /* Read the EEPROM */
-       err = iwl3945_eeprom_init(priv);
+       err = iwl3945_init_geos(priv);
        if (err) {
-               IWL_ERROR("Unable to init EEPROM\n");
-               goto out_remove_sysfs;
+               IWL_ERROR("initializing geos failed: %d\n", err);
+               goto out_free_channel_map;
        }
-       /* MAC Address location in EEPROM same for 3945/4965 */
-       get_eeprom_mac(priv, priv->mac_addr);
-       IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
-       SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 
-       err = iwl3945_init_channel_map(priv);
-       if (err) {
-               IWL_ERROR("initializing regulatory failed: %d\n", err);
-               goto out_remove_sysfs;
+       printk(KERN_INFO DRV_NAME
+               ": 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_param_disable) {
+               set_bit(STATUS_RF_KILL_SW, &priv->status);
+               IWL_DEBUG_INFO("Radio disabled.\n");
        }
 
-       err = iwl3945_init_geos(priv);
+
+       /***********************
+        * 8. Setup Services
+        * ********************/
+
+       spin_lock_irqsave(&priv->lock, flags);
+       iwl3945_disable_interrupts(priv);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
        if (err) {
-               IWL_ERROR("initializing geos failed: %d\n", err);
-               goto out_free_channel_map;
+               IWL_ERROR("failed to create sysfs device attributes\n");
+               goto out_free_geos;
        }
 
+       iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
+       iwl3945_setup_deferred_work(priv);
+       iwl3945_setup_rx_handlers(priv);
+
+       /***********************
+        * 9. Conclude
+        * ********************/
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+
+       /*********************************
+        * 10. Setup and Register mac80211
+        * *******************************/
+
        err = ieee80211_register_hw(priv->hw);
        if (err) {
                IWL_ERROR("Failed to register network device (error %d)\n", err);
-               goto out_free_geos;
+               goto  out_remove_sysfs;
        }
 
        priv->hw->conf.beacon_int = 100;
        priv->mac80211_registered = 1;
-       pci_save_state(pdev);
-       pci_disable_device(pdev);
+
+
+       err = iwl3945_rfkill_init(priv);
+       if (err)
+               IWL_ERROR("Unable to initialize RFKILL system. "
+                                 "Ignoring error: %d\n", err);
 
        return 0;
 
+ out_remove_sysfs:
+       sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
  out_free_geos:
        iwl3945_free_geos(priv);
  out_free_channel_map:
        iwl3945_free_channel_map(priv);
- out_remove_sysfs:
-       sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+
 
  out_release_irq:
        destroy_workqueue(priv->workqueue);
@@ -8197,8 +8094,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 {
        struct iwl3945_priv *priv = pci_get_drvdata(pdev);
-       struct list_head *p, *q;
-       int i;
        unsigned long flags;
 
        if (!priv)
@@ -8219,16 +8114,9 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
        iwl_synchronize_irq(priv);
 
-       /* Free MAC hash list for ADHOC */
-       for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
-               list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
-                       list_del(p);
-                       kfree(list_entry(p, struct iwl3945_ibss_seq, list));
-               }
-       }
-
        sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
+       iwl3945_rfkill_unregister(priv);
        iwl3945_dealloc_ucode_pci(priv);
 
        if (priv->rxq.bd)
@@ -8238,9 +8126,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
        iwl3945_unset_hw_setting(priv);
        iwl3945_clear_stations_table(priv);
 
-       if (priv->mac80211_registered) {
+       if (priv->mac80211_registered)
                ieee80211_unregister_hw(priv->hw);
-       }
 
        /*netif_stop_queue(dev); */
        flush_workqueue(priv->workqueue);
@@ -8258,7 +8145,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
        iwl3945_free_channel_map(priv);
        iwl3945_free_geos(priv);
-
+       kfree(priv->scan);
        if (priv->ibss_beacon)
                dev_kfree_skb(priv->ibss_beacon);
 
@@ -8297,6 +8184,114 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)
 
 #endif /* CONFIG_PM */
 
+/*************** RFKILL FUNCTIONS **********/
+#ifdef CONFIG_IWL3945_RFKILL
+/* software rf-kill from user */
+static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
+{
+       struct iwl3945_priv *priv = data;
+       int err = 0;
+
+       if (!priv->rfkill)
+       return 0;
+
+       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+               return 0;
+
+       IWL_DEBUG_RF_KILL("we received soft RFKILL set to state %d\n", state);
+       mutex_lock(&priv->mutex);
+
+       switch (state) {
+       case RFKILL_STATE_UNBLOCKED:
+               if (iwl3945_is_rfkill_hw(priv)) {
+                       err = -EBUSY;
+                       goto out_unlock;
+               }
+               iwl3945_radio_kill_sw(priv, 0);
+               break;
+       case RFKILL_STATE_SOFT_BLOCKED:
+               iwl3945_radio_kill_sw(priv, 1);
+               break;
+       default:
+               IWL_WARNING("we received unexpected RFKILL state %d\n", state);
+               break;
+       }
+out_unlock:
+       mutex_unlock(&priv->mutex);
+
+       return err;
+}
+
+int iwl3945_rfkill_init(struct iwl3945_priv *priv)
+{
+       struct device *device = wiphy_dev(priv->hw->wiphy);
+       int ret = 0;
+
+       BUG_ON(device == NULL);
+
+       IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
+       priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
+       if (!priv->rfkill) {
+               IWL_ERROR("Unable to allocate rfkill device.\n");
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       priv->rfkill->name = priv->cfg->name;
+       priv->rfkill->data = priv;
+       priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
+       priv->rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill;
+       priv->rfkill->user_claim_unsupported = 1;
+
+       priv->rfkill->dev.class->suspend = NULL;
+       priv->rfkill->dev.class->resume = NULL;
+
+       ret = rfkill_register(priv->rfkill);
+       if (ret) {
+               IWL_ERROR("Unable to register rfkill: %d\n", ret);
+               goto freed_rfkill;
+       }
+
+       IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
+       return ret;
+
+freed_rfkill:
+       if (priv->rfkill != NULL)
+               rfkill_free(priv->rfkill);
+       priv->rfkill = NULL;
+
+error:
+       IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
+       return ret;
+}
+
+void iwl3945_rfkill_unregister(struct iwl3945_priv *priv)
+{
+       if (priv->rfkill)
+               rfkill_unregister(priv->rfkill);
+
+       priv->rfkill = NULL;
+}
+
+/* set rf-kill to the right state. */
+void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv)
+{
+
+       if (!priv->rfkill)
+               return;
+
+       if (iwl3945_is_rfkill_hw(priv)) {
+               rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
+               return;
+       }
+
+       if (!iwl3945_is_rfkill_sw(priv))
+               rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
+       else
+               rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
+}
+#endif
+
 /*****************************************************************************
  *
  * driver and module entry point
@@ -8360,6 +8355,8 @@ static void __exit iwl3945_exit(void)
        iwl3945_rate_control_unregister();
 }
 
+MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
+
 module_param_named(antenna, iwl3945_param_antenna, int, 0444);
 MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
 module_param_named(disable, iwl3945_param_disable, int, 0444);