iwlwifi: fix and add missing sta_lock usage
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl3945-base.c
index 4d0394b..82beeb5 100644 (file)
@@ -196,6 +196,7 @@ static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv,
 static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
 {
        unsigned long flags;
+       struct iwl_addsta_cmd sta_cmd;
 
        spin_lock_irqsave(&priv->sta_lock, flags);
        memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
@@ -204,11 +205,11 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
        priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
        priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
        priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+       memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
        IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
-       iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0);
-       return 0;
+       return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 
 static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
@@ -473,10 +474,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        u8 unicast;
        u8 sta_id;
        u8 tid = 0;
-       u16 seq_number = 0;
        __le16 fc;
        u8 wait_write_ptr = 0;
-       u8 *qc = NULL;
        unsigned long flags;
 
        spin_lock_irqsave(&priv->lock, flags);
@@ -508,11 +507,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        hdr_len = ieee80211_hdrlen(fc);
 
-       /* Find (or create) index into station table for destination station */
-       if (info->flags & IEEE80211_TX_CTL_INJECTED)
-               sta_id = priv->hw_params.bcast_sta_id;
-       else
-               sta_id = iwl_get_sta_id(priv, hdr);
+       /* Find index into station table for destination station */
+       sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta);
        if (sta_id == IWL_INVALID_STATION) {
                IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
                               hdr->addr1);
@@ -522,16 +518,10 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id);
 
        if (ieee80211_is_data_qos(fc)) {
-               qc = ieee80211_get_qos_ctl(hdr);
+               u8 *qc = ieee80211_get_qos_ctl(hdr);
                tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
                if (unlikely(tid >= MAX_TID_COUNT))
                        goto drop;
-               seq_number = priv->stations[sta_id].tid[tid].seq_number &
-                               IEEE80211_SCTL_SEQ;
-               hdr->seq_ctrl = cpu_to_le16(seq_number) |
-                       (hdr->seq_ctrl &
-                               cpu_to_le16(IEEE80211_SCTL_FRAG));
-               seq_number += 0x10;
        }
 
        /* Descriptor for chosen Tx queue */
@@ -590,8 +580,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        if (!ieee80211_has_morefrags(hdr->frame_control)) {
                txq->need_update = 1;
-               if (qc)
-                       priv->stations[sta_id].tid[tid].seq_number = seq_number;
        } else {
                wait_write_ptr = 1;
                txq->need_update = 0;
@@ -956,7 +944,7 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
         * statistics request from the host as well as for the periodic
         * statistics notifications (after received beacons) from the uCode.
         */
-       priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics;
+       priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics;
        priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
 
        iwl_setup_rx_scan_handlers(priv);
@@ -1603,9 +1591,6 @@ static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
        return pos;
 }
 
-/* For sanity check only.  Actual size is determined by uCode, typ. 512 */
-#define IWL3945_MAX_EVENT_LOG_SIZE (512)
-
 #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
 
 int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
@@ -1632,16 +1617,16 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
        num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
        next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
 
-       if (capacity > IWL3945_MAX_EVENT_LOG_SIZE) {
+       if (capacity > priv->cfg->max_event_log_size) {
                IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
-                       capacity, IWL3945_MAX_EVENT_LOG_SIZE);
-               capacity = IWL3945_MAX_EVENT_LOG_SIZE;
+                       capacity, priv->cfg->max_event_log_size);
+               capacity = priv->cfg->max_event_log_size;
        }
 
-       if (next_entry > IWL3945_MAX_EVENT_LOG_SIZE) {
+       if (next_entry > priv->cfg->max_event_log_size) {
                IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
-                       next_entry, IWL3945_MAX_EVENT_LOG_SIZE);
-               next_entry = IWL3945_MAX_EVENT_LOG_SIZE;
+                       next_entry, priv->cfg->max_event_log_size);
+               next_entry = priv->cfg->max_event_log_size;
        }
 
        size = num_wraps ? capacity : next_entry;
@@ -1850,7 +1835,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
                                         enum ieee80211_band band,
                                     u8 is_active, u8 n_probes,
-                                    struct iwl3945_scan_channel *scan_ch)
+                                    struct iwl3945_scan_channel *scan_ch,
+                                    struct ieee80211_vif *vif)
 {
        struct ieee80211_channel *chan;
        const struct ieee80211_supported_band *sband;
@@ -1864,7 +1850,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
                return 0;
 
        active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
-       passive_dwell = iwl_get_passive_dwell_time(priv, band);
+       passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
 
        if (passive_dwell <= active_dwell)
                passive_dwell = active_dwell + 1;
@@ -1946,7 +1932,7 @@ static void iwl3945_init_hw_rates(struct iwl_priv *priv,
 {
        int i;
 
-       for (i = 0; i < IWL_RATE_COUNT; i++) {
+       for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
                rates[i].bitrate = iwl3945_rates[i].ieee * 5;
                rates[i].hw_value = i; /* Rate scaling will work on indexes */
                rates[i].hw_value_short = i;
@@ -2112,6 +2098,28 @@ static void iwl3945_nic_start(struct iwl_priv *priv)
        iwl_write32(priv, CSR_RESET, 0);
 }
 
+#define IWL3945_UCODE_GET(item)                                                \
+static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\
+{                                                                      \
+       return le32_to_cpu(ucode->u.v1.item);                           \
+}
+
+static u32 iwl3945_ucode_get_header_size(u32 api_ver)
+{
+       return 24;
+}
+
+static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode)
+{
+       return (u8 *) ucode->u.v1.data;
+}
+
+IWL3945_UCODE_GET(inst_size);
+IWL3945_UCODE_GET(data_size);
+IWL3945_UCODE_GET(init_size);
+IWL3945_UCODE_GET(init_data_size);
+IWL3945_UCODE_GET(boot_size);
+
 /**
  * iwl3945_read_ucode - Read uCode images from disk file.
  *
@@ -2160,7 +2168,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
                goto error;
 
        /* Make sure that we got at least our header! */
-       if (ucode_raw->size <  priv->cfg->ops->ucode->get_header_size(1)) {
+       if (ucode_raw->size <  iwl3945_ucode_get_header_size(1)) {
                IWL_ERR(priv, "File size way too small!\n");
                ret = -EINVAL;
                goto err_release;
@@ -2171,13 +2179,12 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
 
        priv->ucode_ver = le32_to_cpu(ucode->ver);
        api_ver = IWL_UCODE_API(priv->ucode_ver);
-       inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
-       data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
-       init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
-       init_data_size =
-               priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
-       boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
-       src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
+       inst_size = iwl3945_ucode_get_inst_size(ucode);
+       data_size = iwl3945_ucode_get_data_size(ucode);
+       init_size = iwl3945_ucode_get_init_size(ucode);
+       init_data_size = iwl3945_ucode_get_init_data_size(ucode);
+       boot_size = iwl3945_ucode_get_boot_size(ucode);
+       src = iwl3945_ucode_get_data(ucode);
 
        /* api_ver should match the api version forming part of the
         * firmware filename ... but we don't check for that and only rely
@@ -2226,7 +2233,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
 
 
        /* Verify size of file vs. image size info in file's header */
-       if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) +
+       if (ucode_raw->size != iwl3945_ucode_get_header_size(api_ver) +
                inst_size + data_size + init_size +
                init_data_size + boot_size) {
 
@@ -2525,11 +2532,11 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
                active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
        } else {
                /* Initialize our rx_config data */
-               iwl_connection_init_rx_config(priv, priv->iw_mode);
+               iwl_connection_init_rx_config(priv, NULL);
        }
 
        /* Configure Bluetooth device coexistence support */
-       iwl_send_bt_config(priv);
+       priv->cfg->ops->hcmd->send_bt_config(priv);
 
        /* Configure the adapter for unassociated operation */
        iwlcore_commit_rxon(priv);
@@ -2564,7 +2571,9 @@ static void __iwl3945_down(struct iwl_priv *priv)
                set_bit(STATUS_EXIT_PENDING, &priv->status);
 
        /* Station information will now be cleared in device */
-       iwl_clear_ucode_stations(priv, true);
+       iwl_clear_ucode_stations(priv);
+       iwl_dealloc_bcast_station(priv);
+       iwl_clear_driver_stations(priv);
 
        /* Unblock any waiting calls */
        wake_up_interruptible_all(&priv->wait_command_queue);
@@ -2645,6 +2654,10 @@ static int __iwl3945_up(struct iwl_priv *priv)
 {
        int rc, i;
 
+       rc = iwl_alloc_bcast_station(priv, false);
+       if (rc)
+               return rc;
+
        if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
                IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
                return -EIO;
@@ -2793,11 +2806,8 @@ static void iwl3945_rfkill_poll(struct work_struct *data)
 
 }
 
-#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
-static void iwl3945_bg_request_scan(struct work_struct *data)
+void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, request_scan);
        struct iwl_host_cmd cmd = {
                .id = REPLY_SCAN_CMD,
                .len = sizeof(struct iwl3945_scan_cmd),
@@ -2811,8 +2821,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
        conf = ieee80211_get_hw_conf(priv->hw);
 
-       mutex_lock(&priv->mutex);
-
        cancel_delayed_work(&priv->scan_check);
 
        if (!iwl_is_ready(priv)) {
@@ -2855,20 +2863,15 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                goto done;
        }
 
-       if (!priv->scan_bands) {
-               IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n");
-               goto done;
-       }
-
-       if (!priv->scan) {
-               priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) +
-                                    IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-               if (!priv->scan) {
+       if (!priv->scan_cmd) {
+               priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) +
+                                        IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+               if (!priv->scan_cmd) {
                        IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
                        goto done;
                }
        }
-       scan = priv->scan;
+       scan = priv->scan_cmd;
        memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);
 
        scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
@@ -2884,7 +2887,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
 
                spin_lock_irqsave(&priv->lock, flags);
-               interval = priv->beacon_int;
+               interval = vif ? vif->bss_conf.beacon_int : 0;
                spin_unlock_irqrestore(&priv->lock, flags);
 
                scan->suspend_time = 0;
@@ -2937,22 +2940,26 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
        /* flags + rate selection */
 
-       if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
+       switch (priv->scan_band) {
+       case 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;
-       } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
+               break;
+       case IEEE80211_BAND_5GHZ:
                scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
                /*
                 * If active scaning is requested but a certain channel
                 * is marked passive, we can do active scanning if we
                 * detect transmissions.
                 */
-               scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
+               scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+                                               IWL_GOOD_CRC_TH_DISABLED;
                band = IEEE80211_BAND_5GHZ;
-       } else {
-               IWL_WARN(priv, "Invalid scan band count\n");
+               break;
+       default:
+               IWL_WARN(priv, "Invalid scan band\n");
                goto done;
        }
 
@@ -2973,12 +2980,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        /* select Rx antennas */
        scan->flags |= iwl3945_get_antenna_flags(priv);
 
-       if (iwl_is_monitor_mode(priv))
-               scan->filter_flags = RXON_FILTER_PROMISC_MSK;
-
        scan->channel_count =
                iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
-                       (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
+                       (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
 
        if (scan->channel_count == 0) {
                IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
@@ -2997,7 +3001,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        queue_delayed_work(priv->workqueue, &priv->scan_check,
                           IWL_SCAN_CHECK_WATCHDOG);
 
-       mutex_unlock(&priv->mutex);
        return;
 
  done:
@@ -3011,7 +3014,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
        /* inform mac80211 scan aborted */
        queue_work(priv->workqueue, &priv->scan_completed);
-       mutex_unlock(&priv->mutex);
 }
 
 static void iwl3945_bg_restart(struct work_struct *data)
@@ -3053,28 +3055,25 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
        mutex_unlock(&priv->mutex);
 }
 
-#define IWL_DELAY_NEXT_SCAN (HZ*2)
-
-void iwl3945_post_associate(struct iwl_priv *priv)
+void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
        int rc = 0;
        struct ieee80211_conf *conf = NULL;
 
-       if (priv->iw_mode == NL80211_IFTYPE_AP) {
+       if (!vif || !priv->is_open)
+               return;
+
+       if (vif->type == NL80211_IFTYPE_AP) {
                IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
                return;
        }
 
-
        IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-                       priv->assoc_id, priv->active_rxon.bssid_addr);
+                       vif->bss_conf.aid, priv->active_rxon.bssid_addr);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       if (!priv->vif || !priv->is_open)
-               return;
-
        iwl_scan_cancel_timeout(priv, 200);
 
        conf = ieee80211_get_hw_conf(priv->hw);
@@ -3083,7 +3082,7 @@ void iwl3945_post_associate(struct iwl_priv *priv)
        iwlcore_commit_rxon(priv);
 
        memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
-       iwl_setup_rxon_timing(priv);
+       iwl_setup_rxon_timing(priv, vif);
        rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
                              sizeof(priv->rxon_timing), &priv->rxon_timing);
        if (rc)
@@ -3092,56 +3091,40 @@ void iwl3945_post_associate(struct iwl_priv *priv)
 
        priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
 
-       priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
+       priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid);
 
        IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
-                       priv->assoc_id, priv->beacon_int);
+                       vif->bss_conf.aid, vif->bss_conf.beacon_int);
 
-       if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+       if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
                priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
        else
                priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 
        if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
-               if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
+               if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
                        priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
                else
                        priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
-               if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
+               if (vif->type == NL80211_IFTYPE_ADHOC)
                        priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-
        }
 
        iwlcore_commit_rxon(priv);
 
-       switch (priv->iw_mode) {
+       switch (vif->type) {
        case NL80211_IFTYPE_STATION:
                iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
                break;
-
        case NL80211_IFTYPE_ADHOC:
-
-               priv->assoc_id = 1;
-               iwl_add_local_station(priv, priv->bssid, false);
-               iwl3945_sync_sta(priv, IWL_STA_ID,
-                               (priv->band == IEEE80211_BAND_5GHZ) ?
-                               IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
-                                CMD_ASYNC);
-               iwl3945_rate_scale_init(priv->hw, IWL_STA_ID);
-
                iwl3945_send_beacon_cmd(priv);
-
                break;
-
        default:
-                IWL_ERR(priv, "%s Should not be called in %d mode\n",
-                          __func__, priv->iw_mode);
+               IWL_ERR(priv, "%s Should not be called in %d mode\n",
+                       __func__, vif->type);
                break;
        }
-
-       /* we have just associated, don't start scan too early */
-       priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
 }
 
 /*****************************************************************************
@@ -3263,7 +3246,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
        return NETDEV_TX_OK;
 }
 
-void iwl3945_config_ap(struct iwl_priv *priv)
+void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
        int rc = 0;
 
@@ -3279,7 +3262,7 @@ void iwl3945_config_ap(struct iwl_priv *priv)
 
                /* RXON Timing */
                memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
-               iwl_setup_rxon_timing(priv);
+               iwl_setup_rxon_timing(priv, vif);
                rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
                                      sizeof(priv->rxon_timing),
                                      &priv->rxon_timing);
@@ -3287,9 +3270,10 @@ void iwl3945_config_ap(struct iwl_priv *priv)
                        IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
                                        "Attempting to continue.\n");
 
-               /* FIXME: what should be the assoc_id for AP? */
-               priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
-               if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+               priv->staging_rxon.assoc_id = 0;
+
+               if (vif->bss_conf.assoc_capability &
+                                       WLAN_CAPABILITY_SHORT_PREAMBLE)
                        priv->staging_rxon.flags |=
                                RXON_FLG_SHORT_PREAMBLE_MSK;
                else
@@ -3297,22 +3281,21 @@ void iwl3945_config_ap(struct iwl_priv *priv)
                                ~RXON_FLG_SHORT_PREAMBLE_MSK;
 
                if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
-                       if (priv->assoc_capability &
-                               WLAN_CAPABILITY_SHORT_SLOT_TIME)
+                       if (vif->bss_conf.assoc_capability &
+                                       WLAN_CAPABILITY_SHORT_SLOT_TIME)
                                priv->staging_rxon.flags |=
                                        RXON_FLG_SHORT_SLOT_MSK;
                        else
                                priv->staging_rxon.flags &=
                                        ~RXON_FLG_SHORT_SLOT_MSK;
 
-                       if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
+                       if (vif->type == NL80211_IFTYPE_ADHOC)
                                priv->staging_rxon.flags &=
                                        ~RXON_FLG_SHORT_SLOT_MSK;
                }
                /* restore RXON assoc */
                priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
                iwlcore_commit_rxon(priv);
-               iwl_add_local_station(priv, iwl_bcast_addr, false);
        }
        iwl3945_send_beacon_cmd(priv);
 
@@ -3327,7 +3310,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                               struct ieee80211_key_conf *key)
 {
        struct iwl_priv *priv = hw->priv;
-       const u8 *addr;
        int ret = 0;
        u8 sta_id = IWL_INVALID_STATION;
        u8 static_key;
@@ -3339,16 +3321,12 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                return -EOPNOTSUPP;
        }
 
-       addr = sta ? sta->addr : iwl_bcast_addr;
        static_key = !iwl_is_associated(priv);
 
        if (!static_key) {
-               sta_id = iwl_find_station(priv, addr);
-               if (sta_id == IWL_INVALID_STATION) {
-                       IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
-                                           addr);
+               sta_id = iwl_sta_id_or_broadcast(priv, sta);
+               if (sta_id == IWL_INVALID_STATION)
                        return -EINVAL;
-               }
        }
 
        mutex_lock(&priv->mutex);
@@ -3384,10 +3362,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
                               struct ieee80211_sta *sta)
 {
        struct iwl_priv *priv = hw->priv;
+       struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv;
        int ret;
-       bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION;
+       bool is_ap = vif->type == NL80211_IFTYPE_STATION;
        u8 sta_id;
 
+       sta_priv->common.sta_id = IWL_INVALID_STATION;
+
        IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
                        sta->addr);
 
@@ -3400,16 +3381,14 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
                return ret;
        }
 
+       sta_priv->common.sta_id = sta_id;
+
        /* Initialize rate scaling */
        IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
                       sta->addr);
        iwl3945_rs_rate_init(priv, sta, sta_id);
 
        return 0;
-
-
-
-       return ret;
 }
 /*****************************************************************************
  *
@@ -3674,44 +3653,6 @@ static ssize_t show_channels(struct device *d,
 
 static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
 
-static ssize_t show_statistics(struct device *d,
-                              struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       u32 size = sizeof(struct iwl3945_notif_statistics);
-       u32 len = 0, ofs = 0;
-       u8 *data = (u8 *)&priv->_3945.statistics;
-       int rc = 0;
-
-       if (!iwl_is_alive(priv))
-               return -EAGAIN;
-
-       mutex_lock(&priv->mutex);
-       rc = iwl_send_statistics_request(priv, CMD_SYNC, false);
-       mutex_unlock(&priv->mutex);
-
-       if (rc) {
-               len = sprintf(buf,
-                             "Error sending statistics request: 0x%08X\n", rc);
-               return len;
-       }
-
-       while (size && (PAGE_SIZE - len)) {
-               hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
-                                  PAGE_SIZE - len, 1);
-               len = strlen(buf);
-               if (PAGE_SIZE - len)
-                       buf[len++] = '\n';
-
-               ofs += 16;
-               size -= min(size, 16U);
-       }
-
-       return len;
-}
-
-static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
-
 static ssize_t show_antenna(struct device *d,
                            struct device_attribute *attr, char *buf)
 {
@@ -3795,8 +3736,8 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
        INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
        INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
        INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
-       INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
        INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
+       INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
        INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
 
        iwl3945_hw_setup_deferred_work(priv);
@@ -3819,6 +3760,7 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
        cancel_delayed_work_sync(&priv->init_alive_start);
        cancel_delayed_work(&priv->scan_check);
        cancel_delayed_work(&priv->alive_start);
+       cancel_work_sync(&priv->start_internal_scan);
        cancel_work_sync(&priv->beacon_update);
        if (priv->cfg->ops->lib->recover_from_tx_stall)
                del_timer_sync(&priv->monitor_recover);
@@ -3832,7 +3774,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
        &dev_attr_filter_flags.attr,
        &dev_attr_measurement.attr,
        &dev_attr_retry_rate.attr,
-       &dev_attr_statistics.attr,
        &dev_attr_status.attr,
        &dev_attr_temperature.attr,
        &dev_attr_tx_power.attr,
@@ -3922,6 +3863,8 @@ err:
        return ret;
 }
 
+#define IWL3945_MAX_PROBE_REQUEST      200
+
 static int iwl3945_setup_mac(struct iwl_priv *priv)
 {
        int ret;
@@ -3929,10 +3872,10 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
 
        hw->rate_control_algorithm = "iwl-3945-rs";
        hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
+       hw->vif_data_size = sizeof(struct iwl_vif_priv);
 
        /* Tell mac80211 our characteristics */
        hw->flags = IEEE80211_HW_SIGNAL_DBM |
-                   IEEE80211_HW_NOISE_DBM |
                    IEEE80211_HW_SPECTRUM_MGMT;
 
        if (!priv->cfg->broken_powersave)
@@ -3943,12 +3886,12 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
                BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_ADHOC);
 
-       hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY |
+       hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
                            WIPHY_FLAG_DISABLE_BEACON_HINTS;
 
        hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
        /* we create the 802.11 header and a zero-length SSID element */
-       hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
+       hw->wiphy->max_scan_ie_len = IWL3945_MAX_PROBE_REQUEST - 24 - 2;
 
        /* Default value; 4 EDCA QOS priorities */
        hw->queues = 4;
@@ -4255,7 +4198,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
        iwl_free_channel_map(priv);
        iwlcore_free_geos(priv);
-       kfree(priv->scan);
+       kfree(priv->scan_cmd);
        if (priv->ibss_beacon)
                dev_kfree_skb(priv->ibss_beacon);