Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / drivers / net / wireless / iwlwifi / iwl3945-base.c
index 4465320..6b42ea2 100644 (file)
@@ -149,7 +149,7 @@ out:
  *
  * NOTE:  This does not clear or otherwise alter the device's station table.
  */
-static void iwl3945_clear_stations_table(struct iwl_priv *priv)
+void iwl3945_clear_stations_table(struct iwl_priv *priv)
 {
        unsigned long flags;
 
@@ -164,7 +164,7 @@ static void iwl3945_clear_stations_table(struct iwl_priv *priv)
 /**
  * iwl3945_add_station - Add station to station tables in driver and device
  */
-u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags)
+u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info)
 {
        int i;
        int index = IWL_INVALID_STATION;
@@ -233,50 +233,6 @@ u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flag
 
 }
 
-static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
-{
-       int rc = 0;
-       struct iwl_rx_packet *res = NULL;
-       struct iwl3945_rxon_assoc_cmd rxon_assoc;
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_RXON_ASSOC,
-               .len = sizeof(rxon_assoc),
-               .meta.flags = CMD_WANT_SKB,
-               .data = &rxon_assoc,
-       };
-       const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
-       const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
-
-       if ((rxon1->flags == rxon2->flags) &&
-           (rxon1->filter_flags == rxon2->filter_flags) &&
-           (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
-           (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
-               IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
-               return 0;
-       }
-
-       rxon_assoc.flags = priv->staging_rxon.flags;
-       rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
-       rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
-       rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
-       rxon_assoc.reserved = 0;
-
-       rc = iwl_send_cmd_sync(priv, &cmd);
-       if (rc)
-               return rc;
-
-       res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
-       if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
-               rc = -EIO;
-       }
-
-       priv->alloc_rxb_skb--;
-       dev_kfree_skb_any(cmd.meta.u.skb);
-
-       return rc;
-}
-
 /**
  * iwl3945_get_antenna_flags - Get antenna flags for RXON command
  * @priv: eeprom and antenna fields are used to determine antenna flags
@@ -314,150 +270,6 @@ __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
        return 0;               /* "diversity" is default if error */
 }
 
-/**
- * iwl3945_commit_rxon - commit staging_rxon to hardware
- *
- * The RXON command in staging_rxon is committed to the hardware and
- * the active_rxon structure is updated with the new data.  This
- * function correctly transitions out of the RXON_ASSOC_MSK state if
- * a HW tune is required based on the RXON structure changes.
- */
-static int iwl3945_commit_rxon(struct iwl_priv *priv)
-{
-       /* cast away the const for active_rxon in this function */
-       struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
-       struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon;
-       int rc = 0;
-       bool new_assoc =
-               !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
-
-       if (!iwl_is_alive(priv))
-               return -1;
-
-       /* always get timestamp with Rx frame */
-       staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK;
-
-       /* select antenna */
-       staging_rxon->flags &=
-           ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
-       staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
-
-       rc = iwl_check_rxon_cmd(priv);
-       if (rc) {
-               IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
-               return -EINVAL;
-       }
-
-       /* If we don't need to send a full RXON, we can use
-        * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
-        * and other flags for the current radio configuration. */
-       if (!iwl_full_rxon_required(priv)) {
-               rc = iwl3945_send_rxon_assoc(priv);
-               if (rc) {
-                       IWL_ERR(priv, "Error setting RXON_ASSOC "
-                                 "configuration (%d).\n", rc);
-                       return rc;
-               }
-
-               memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
-
-               return 0;
-       }
-
-       /* If we are currently associated and the new config requires
-        * an RXON_ASSOC and the new config wants the associated mask enabled,
-        * we must clear the associated from the active configuration
-        * before we apply the new config */
-       if (iwl_is_associated(priv) && new_assoc) {
-               IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
-               active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-               /*
-                * reserved4 and 5 could have been filled by the iwlcore code.
-                * Let's clear them before pushing to the 3945.
-                */
-               active_rxon->reserved4 = 0;
-               active_rxon->reserved5 = 0;
-               rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
-                                     sizeof(struct iwl3945_rxon_cmd),
-                                     &priv->active_rxon);
-
-               /* If the mask clearing failed then we set
-                * active_rxon back to what it was previously */
-               if (rc) {
-                       active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-                       IWL_ERR(priv, "Error clearing ASSOC_MSK on current "
-                                 "configuration (%d).\n", rc);
-                       return rc;
-               }
-       }
-
-       IWL_DEBUG_INFO(priv, "Sending RXON\n"
-                      "* with%s RXON_FILTER_ASSOC_MSK\n"
-                      "* channel = %d\n"
-                      "* bssid = %pM\n",
-                      (new_assoc ? "" : "out"),
-                      le16_to_cpu(staging_rxon->channel),
-                      staging_rxon->bssid_addr);
-
-       /*
-        * reserved4 and 5 could have been filled by the iwlcore code.
-        * Let's clear them before pushing to the 3945.
-        */
-       staging_rxon->reserved4 = 0;
-       staging_rxon->reserved5 = 0;
-
-       iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
-
-       /* Apply the new configuration */
-       rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
-                             sizeof(struct iwl3945_rxon_cmd),
-                             staging_rxon);
-       if (rc) {
-               IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
-               return rc;
-       }
-
-       memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
-
-       iwl3945_clear_stations_table(priv);
-
-       /* If we issue a new RXON command which required a tune then we must
-        * send a new TXPOWER command or we won't be able to Tx any frames */
-       rc = priv->cfg->ops->lib->send_tx_power(priv);
-       if (rc) {
-               IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
-               return rc;
-       }
-
-       /* Add the broadcast address so we can send broadcast frames */
-       if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) ==
-           IWL_INVALID_STATION) {
-               IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
-               return -EIO;
-       }
-
-       /* If we have set the ASSOC_MSK and we are in BSS mode then
-        * add the IWL_AP_ID to the station rate table */
-       if (iwl_is_associated(priv) &&
-           (priv->iw_mode == NL80211_IFTYPE_STATION))
-               if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr,
-                                       1, 0)
-                   == IWL_INVALID_STATION) {
-                       IWL_ERR(priv, "Error adding AP address for transmit\n");
-                       return -EIO;
-               }
-
-       /* Init the hardware's rate fallback order based on the band */
-       rc = iwl3945_init_hw_rate_table(priv);
-       if (rc) {
-               IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc);
-               return -EIO;
-       }
-
-       return 0;
-}
-
 static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
                                   struct ieee80211_key_conf *keyconf,
                                   u8 sta_id)
@@ -485,14 +297,14 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
        memcpy(priv->stations_39[sta_id].sta.key.key, keyconf->key,
               keyconf->keylen);
 
-       if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+       if ((priv->stations_39[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
                        == STA_KEY_FLG_NO_ENC)
-               priv->stations[sta_id].sta.key.key_offset =
+               priv->stations_39[sta_id].sta.key.key_offset =
                                 iwl_get_free_ucode_key_index(priv);
        /* else, we are overriding an existing key => no need to allocated room
        * in uCode. */
 
-       WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+       WARN(priv->stations_39[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
                "no space for a new key");
 
        priv->stations_39[sta_id].sta.key.key_flags = key_flags;
@@ -560,7 +372,7 @@ static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
                ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id);
                break;
        default:
-               IWL_ERR(priv,"Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
+               IWL_ERR(priv, "Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
                ret = -EINVAL;
        }
 
@@ -758,42 +570,6 @@ static void iwl3945_setup_rxon_timing(struct iwl_priv *priv)
                le16_to_cpu(priv->rxon_timing.atim_window));
 }
 
-static int iwl3945_set_mode(struct iwl_priv *priv, int mode)
-{
-       if (mode == NL80211_IFTYPE_ADHOC) {
-               const struct iwl_channel_info *ch_info;
-
-               ch_info = iwl_get_channel_info(priv,
-                       priv->band,
-                       le16_to_cpu(priv->staging_rxon.channel));
-
-               if (!ch_info || !is_channel_ibss(ch_info)) {
-                       IWL_ERR(priv, "channel %d not IBSS channel\n",
-                                 le16_to_cpu(priv->staging_rxon.channel));
-                       return -EINVAL;
-               }
-       }
-
-       iwl_connection_init_rx_config(priv, mode);
-
-       iwl3945_clear_stations_table(priv);
-
-       /* don't commit rxon if rf-kill is on*/
-       if (!iwl_is_ready_rf(priv))
-               return -EAGAIN;
-
-       cancel_delayed_work(&priv->scan_check);
-       if (iwl_scan_cancel_timeout(priv, 100)) {
-               IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
-               IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-               return -EAGAIN;
-       }
-
-       iwl3945_commit_rxon(priv);
-
-       return 0;
-}
-
 static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
                                      struct ieee80211_tx_info *info,
                                      struct iwl_cmd *cmd,
@@ -900,64 +676,6 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
        tx->next_frame_len = 0;
 }
 
-/**
- * iwl3945_get_sta_id - Find station's index within station table
- */
-static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
-{
-       int sta_id;
-       u16 fc = le16_to_cpu(hdr->frame_control);
-
-       /* If this frame is broadcast or management, use broadcast station id */
-       if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
-           is_multicast_ether_addr(hdr->addr1))
-               return priv->hw_params.bcast_sta_id;
-
-       switch (priv->iw_mode) {
-
-       /* If we are a client station in a BSS network, use the special
-        * AP station entry (that's the only station we communicate with) */
-       case NL80211_IFTYPE_STATION:
-               return IWL_AP_ID;
-
-       /* If we are an AP, then find the station, or use BCAST */
-       case NL80211_IFTYPE_AP:
-               sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
-               if (sta_id != IWL_INVALID_STATION)
-                       return sta_id;
-               return priv->hw_params.bcast_sta_id;
-
-       /* If this frame is going out to an IBSS network, find the station,
-        * or create a new station table entry */
-       case NL80211_IFTYPE_ADHOC: {
-               /* Create new station table entry */
-               sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
-               if (sta_id != IWL_INVALID_STATION)
-                       return sta_id;
-
-               sta_id = iwl3945_add_station(priv, hdr->addr1, 0, CMD_ASYNC);
-
-               if (sta_id != IWL_INVALID_STATION)
-                       return sta_id;
-
-               IWL_DEBUG_DROP(priv, "Station %pM not in station map. "
-                              "Defaulting to broadcast...\n",
-                              hdr->addr1);
-               iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
-               return priv->hw_params.bcast_sta_id;
-       }
-       /* If we are in monitor mode, use BCAST. This is required for
-        * packet injection. */
-       case NL80211_IFTYPE_MONITOR:
-               return priv->hw_params.bcast_sta_id;
-
-       default:
-               IWL_WARN(priv, "Unknown mode of operation: %d\n",
-                       priv->iw_mode);
-               return priv->hw_params.bcast_sta_id;
-       }
-}
-
 /*
  * start REPLY_TX command process
  */
@@ -972,7 +690,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        dma_addr_t phys_addr;
        dma_addr_t txcmd_phys;
        int txq_id = skb_get_queue_mapping(skb);
-       u16 len, idx, len_org, hdr_len;
+       u16 len, idx, len_org, hdr_len; /* TODO: len_org is not used */
        u8 id;
        u8 unicast;
        u8 sta_id;
@@ -1011,7 +729,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        /* drop all data frame if we are not associated */
        if (ieee80211_is_data(fc) &&
-           (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */
+           (!iwl_is_monitor_mode(priv)) && /* packet injection */
            (!iwl_is_associated(priv) ||
             ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
                IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
@@ -1023,7 +741,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        hdr_len = ieee80211_hdrlen(fc);
 
        /* Find (or create) index into station table for destination station */
-       sta_id = iwl3945_get_sta_id(priv, hdr);
+       sta_id = iwl_get_sta_id(priv, hdr);
        if (sta_id == IWL_INVALID_STATION) {
                IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
                               hdr->addr1);
@@ -1074,6 +792,40 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        /* Copy MAC header from skb into command buffer */
        memcpy(tx->hdr, hdr, hdr_len);
 
+
+       if (info->control.hw_key)
+               iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
+
+       /* TODO need this for burst mode later on */
+       iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
+
+       /* set is_hcca to 0; it probably will never be implemented */
+       iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
+
+       /* Total # bytes to be transmitted */
+       len = (u16)skb->len;
+       tx->len = cpu_to_le16(len);
+
+
+       tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
+       tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
+
+       if (!ieee80211_has_morefrags(hdr->frame_control)) {
+               txq->need_update = 1;
+               if (qc)
+                       priv->stations_39[sta_id].tid[tid].seq_number = seq_number;
+       } else {
+               wait_write_ptr = 1;
+               txq->need_update = 0;
+       }
+
+       IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
+                    le16_to_cpu(out_cmd->hdr.sequence));
+       IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags));
+       iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
+       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
+                          ieee80211_hdrlen(fc));
+
        /*
         * Use the first empty entry in this queue's command buffer array
         * to contain the Tx command and MAC header concatenated together
@@ -1096,22 +848,18 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        /* Physical address of this Tx command's header (not MAC header!),
         * within command buffer array. */
-       txcmd_phys = pci_map_single(priv->pci_dev,
-                                   out_cmd, sizeof(struct iwl_cmd),
-                                   PCI_DMA_TODEVICE);
+       txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
+                                   len, PCI_DMA_TODEVICE);
+       /* we do not map meta data ... so we can safely access address to
+        * provide to unmap command*/
        pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
-       pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
-       /* Add buffer containing Tx command and MAC(!) header to TFD's
-        * first entry */
-       txcmd_phys += offsetof(struct iwl_cmd, hdr);
+       pci_unmap_len_set(&out_cmd->meta, len, len);
 
        /* Add buffer containing Tx command and MAC(!) header to TFD's
         * first entry */
        priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
                                                   txcmd_phys, len, 1, 0);
 
-       if (info->control.hw_key)
-               iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
 
        /* Set up TFD's 2nd entry to point directly to remainder of skb,
         * if any (802.11 null frames have no payload). */
@@ -1124,32 +872,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                                                           0, U32_PAD(len));
        }
 
-       /* Total # bytes to be transmitted */
-       len = (u16)skb->len;
-       tx->len = cpu_to_le16(len);
-
-       /* TODO need this for burst mode later on */
-       iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
-
-       /* set is_hcca to 0; it probably will never be implemented */
-       iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
-
-       tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
-       tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
-
-       if (!ieee80211_has_morefrags(hdr->frame_control)) {
-               txq->need_update = 1;
-               if (qc)
-                       priv->stations_39[sta_id].tid[tid].seq_number = seq_number;
-       } else {
-               wait_write_ptr = 1;
-               txq->need_update = 0;
-       }
-
-       iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
-
-       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
-                          ieee80211_hdrlen(fc));
 
        /* Tell device the write index *just past* this latest filled TFD */
        q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
@@ -1168,7 +890,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                        spin_unlock_irqrestore(&priv->lock, flags);
                }
 
-               ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb));
+               iwl_stop_queue(priv, skb_get_queue_mapping(skb));
        }
 
        return 0;
@@ -1661,6 +1383,36 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv)
        spin_unlock_irqrestore(&rxq->lock, flags);
 }
 
+void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+       unsigned long flags;
+       int i;
+       spin_lock_irqsave(&rxq->lock, flags);
+       INIT_LIST_HEAD(&rxq->rx_free);
+       INIT_LIST_HEAD(&rxq->rx_used);
+       /* Fill the rx_used queue with _all_ of the Rx buffers */
+       for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+               /* In the reset function, these buffers may have been allocated
+                * to an SKB, so we need to unmap and free potential storage */
+               if (rxq->pool[i].skb != NULL) {
+                       pci_unmap_single(priv->pci_dev,
+                                        rxq->pool[i].real_dma_addr,
+                                        priv->hw_params.rx_buf_size,
+                                        PCI_DMA_FROMDEVICE);
+                       priv->alloc_rxb_skb--;
+                       dev_kfree_skb(rxq->pool[i].skb);
+                       rxq->pool[i].skb = NULL;
+               }
+               list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+       }
+
+       /* Set us so that we have processed and used all buffers, but have
+        * not restocked the Rx queue with fresh buffers */
+       rxq->read = rxq->write = 0;
+       rxq->free_count = 0;
+       spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
 /*
  * this should be called while priv->lock is locked
  */
@@ -1685,6 +1437,33 @@ void iwl3945_rx_replenish(void *data)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
+/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
+ * If an SKB has been detached, the POOL needs to have its SKB set to NULL
+ * This free routine walks the list of POOL entries and if SKB is set to
+ * non NULL it is unmapped and freed
+ */
+static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+       int i;
+       for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+               if (rxq->pool[i].skb != NULL) {
+                       pci_unmap_single(priv->pci_dev,
+                                        rxq->pool[i].real_dma_addr,
+                                        priv->hw_params.rx_buf_size,
+                                        PCI_DMA_FROMDEVICE);
+                       dev_kfree_skb(rxq->pool[i].skb);
+               }
+       }
+
+       pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+                           rxq->dma_addr);
+       pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
+                           rxq->rb_stts, rxq->rb_stts_dma);
+       rxq->bd = NULL;
+       rxq->rb_stts  = NULL;
+}
+
+
 /* Convert linear signal-to-noise ratio into dB */
 static u8 ratio2dB[100] = {
 /*      0   1   2   3   4   5   6   7   8   9 */
@@ -1802,9 +1581,9 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
 
                rxq->queue[i] = NULL;
 
-               pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->real_dma_addr,
-                                           priv->hw_params.rx_buf_size,
-                                           PCI_DMA_FROMDEVICE);
+               pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
+                               priv->hw_params.rx_buf_size,
+                               PCI_DMA_FROMDEVICE);
                pkt = (struct iwl_rx_packet *)rxb->skb->data;
 
                /* Reclaim a command buffer only if this packet is a response
@@ -1825,6 +1604,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
                                "r = %d, i = %d, %s, 0x%02x\n", r, i,
                                get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
                        priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+                       priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
                } else {
                        /* No handling needed */
                        IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR,
@@ -1852,9 +1632,6 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
                        rxb->skb = NULL;
                }
 
-               pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
-                               priv->hw_params.rx_buf_size,
-                               PCI_DMA_FROMDEVICE);
                spin_lock_irqsave(&rxq->lock, flags);
                list_add_tail(&rxb->list, &priv->rxq.rx_used);
                spin_unlock_irqrestore(&rxq->lock, flags);
@@ -2069,9 +1846,9 @@ static void iwl3945_error_recovery(struct iwl_priv *priv)
        memcpy(&priv->staging_rxon, &priv->recovery_rxon,
               sizeof(priv->staging_rxon));
        priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       iwl3945_commit_rxon(priv);
+       iwlcore_commit_rxon(priv);
 
-       iwl3945_add_station(priv, priv->bssid, 1, 0);
+       priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 1, 0, NULL);
 
        spin_lock_irqsave(&priv->lock, flags);
        priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
@@ -2127,6 +1904,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
                /* Tell the device to stop sending interrupts */
                iwl_disable_interrupts(priv);
 
+               priv->isr_stats.hw++;
                iwl_irq_handle_error(priv);
 
                handled |= CSR_INT_BIT_HW_ERR;
@@ -2139,13 +1917,17 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 #ifdef CONFIG_IWLWIFI_DEBUG
        if (priv->debug_level & (IWL_DL_ISR)) {
                /* NIC fires this, but we don't use it, redundant with WAKEUP */
-               if (inta & CSR_INT_BIT_SCD)
+               if (inta & CSR_INT_BIT_SCD) {
                        IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
                                      "the frame/frames.\n");
+                       priv->isr_stats.sch++;
+               }
 
                /* Alive notification via Rx interrupt will do the real work */
-               if (inta & CSR_INT_BIT_ALIVE)
+               if (inta & CSR_INT_BIT_ALIVE) {
                        IWL_DEBUG_ISR(priv, "Alive interrupt\n");
+                       priv->isr_stats.alive++;
+               }
        }
 #endif
        /* Safely ignore these bits for debug checks below */
@@ -2155,6 +1937,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
        if (inta & CSR_INT_BIT_SW_ERR) {
                IWL_ERR(priv, "Microcode SW error detected. "
                        "Restarting 0x%X.\n", inta);
+               priv->isr_stats.sw++;
+               priv->isr_stats.sw_err = inta;
                iwl_irq_handle_error(priv);
                handled |= CSR_INT_BIT_SW_ERR;
        }
@@ -2170,6 +1954,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
                iwl_txq_update_write_ptr(priv, &priv->txq[4]);
                iwl_txq_update_write_ptr(priv, &priv->txq[5]);
 
+               priv->isr_stats.wakeup++;
                handled |= CSR_INT_BIT_WAKEUP;
        }
 
@@ -2178,11 +1963,13 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
         * notifications from uCode come through here*/
        if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
                iwl3945_rx_handle(priv);
+               priv->isr_stats.rx++;
                handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
        }
 
        if (inta & CSR_INT_BIT_FH_TX) {
                IWL_DEBUG_ISR(priv, "Tx interrupt\n");
+               priv->isr_stats.tx++;
 
                iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
                if (!iwl_grab_nic_access(priv)) {
@@ -2193,8 +1980,10 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
                handled |= CSR_INT_BIT_FH_TX;
        }
 
-       if (inta & ~handled)
+       if (inta & ~handled) {
                IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
+               priv->isr_stats.unhandled++;
+       }
 
        if (inta & ~CSR_INI_SET_MASK) {
                IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
@@ -2562,7 +2351,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
 
        /* api_ver should match the api version forming part of the
         * firmware filename ... but we don't check for that and only rely
-        * on the API version read from firware header from here on forward */
+        * on the API version read from firmware header from here on forward */
 
        if (api_ver < api_min || api_ver > api_max) {
                IWL_ERR(priv, "Driver unable to support your firmware API. "
@@ -2836,11 +2625,6 @@ static void iwl3945_init_alive_start(struct iwl_priv *priv)
        queue_work(priv->workqueue, &priv->restart);
 }
 
-
-/* temporary */
-static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw,
-                                    struct sk_buff *skb);
-
 /**
  * iwl3945_alive_start - called after REPLY_ALIVE notification received
  *                   from protocol/runtime uCode (initialization uCode's
@@ -2871,7 +2655,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
                goto restart;
        }
 
-       iwl3945_clear_stations_table(priv);
+       priv->cfg->ops->smgmt->clear_station_table(priv);
 
        rc = iwl_grab_nic_access(priv);
        if (rc) {
@@ -2930,7 +2714,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
        iwl_send_bt_config(priv);
 
        /* Configure the adapter for unassociated operation */
-       iwl3945_commit_rxon(priv);
+       iwlcore_commit_rxon(priv);
 
        iwl3945_reg_txpower_periodic(priv);
 
@@ -2948,9 +2732,12 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
                struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
                                                                priv->vif);
                if (beacon)
-                       iwl3945_mac_beacon_update(priv->hw, beacon);
+                       iwl_mac_beacon_update(priv->hw, beacon);
        }
 
+       if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status))
+               iwl_set_mode(priv, priv->iw_mode);
+
        return;
 
  restart:
@@ -2973,7 +2760,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
                set_bit(STATUS_EXIT_PENDING, &priv->status);
 
        iwl3945_led_unregister(priv);
-       iwl3945_clear_stations_table(priv);
+       priv->cfg->ops->smgmt->clear_station_table(priv);
 
        /* Unblock any waiting calls */
        wake_up_interruptible_all(&priv->wait_command_queue);
@@ -2996,7 +2783,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
                ieee80211_stop_queues(priv->hw);
 
        /* If we have not previously called iwl3945_init() then
-        * clear all bits but the RF Kill and SUSPEND bits and return */
+        * clear all bits but the RF Kill bits and return */
        if (!iwl_is_init(priv)) {
                priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
                                        STATUS_RF_KILL_HW |
@@ -3004,23 +2791,19 @@ static void __iwl3945_down(struct iwl_priv *priv)
                                        STATUS_RF_KILL_SW |
                               test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
                                        STATUS_GEO_CONFIGURED |
-                              test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-                                       STATUS_IN_SUSPEND |
                                test_bit(STATUS_EXIT_PENDING, &priv->status) <<
                                        STATUS_EXIT_PENDING;
                goto exit;
        }
 
-       /* ...otherwise clear out all the status bits but the RF Kill and
-        * SUSPEND bits and continue taking the NIC down. */
+       /* ...otherwise clear out all the status bits but the RF Kill
+        * bits and continue taking the NIC down. */
        priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
                                STATUS_RF_KILL_HW |
                        test_bit(STATUS_RF_KILL_SW, &priv->status) <<
                                STATUS_RF_KILL_SW |
                        test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
                                STATUS_GEO_CONFIGURED |
-                       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-                               STATUS_IN_SUSPEND |
                        test_bit(STATUS_FW_ERROR, &priv->status) <<
                                STATUS_FW_ERROR |
                        test_bit(STATUS_EXIT_PENDING, &priv->status) <<
@@ -3044,7 +2827,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
 
        udelay(5);
 
-       if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
+       if (exit_pending)
                priv->cfg->ops->lib->apm_ops.stop(priv);
        else
                priv->cfg->ops->lib->apm_ops.reset(priv);
@@ -3097,10 +2880,8 @@ static int __iwl3945_up(struct iwl_priv *priv)
                clear_bit(STATUS_RF_KILL_HW, &priv->status);
        else {
                set_bit(STATUS_RF_KILL_HW, &priv->status);
-               if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
-                       IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
-                       return -ENODEV;
-               }
+               IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
+               return -ENODEV;
        }
 
        iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
@@ -3136,7 +2917,7 @@ static int __iwl3945_up(struct iwl_priv *priv)
 
        for (i = 0; i < MAX_HW_RESTARTS; i++) {
 
-               iwl3945_clear_stations_table(priv);
+               priv->cfg->ops->smgmt->clear_station_table(priv);
 
                /* load bootstrap state machine,
                 * load bootstrap program into processor's memory,
@@ -3232,9 +3013,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 n_probes = 2;
+       u8 n_probes = 0;
        enum ieee80211_band band;
-       DECLARE_SSID_BUF(ssid);
+       bool is_active = false;
 
        conf = ieee80211_get_hw_conf(priv->hw);
 
@@ -3333,18 +3114,25 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                               scan_suspend_time, interval);
        }
 
-       /* We should add the ability for user to lock to PASSIVE ONLY */
-       if (priv->one_direct_scan) {
-               IWL_DEBUG_SCAN(priv, "Kicking off one direct scan for '%s'\n",
-                               print_ssid(ssid, priv->direct_ssid,
-                               priv->direct_ssid_len));
-               scan->direct_scan[0].id = WLAN_EID_SSID;
-               scan->direct_scan[0].len = priv->direct_ssid_len;
-               memcpy(scan->direct_scan[0].ssid,
-                      priv->direct_ssid, priv->direct_ssid_len);
-               n_probes++;
+       if (priv->scan_request->n_ssids) {
+               int i, p = 0;
+               IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
+               for (i = 0; i < priv->scan_request->n_ssids; i++) {
+                       /* always does wildcard anyway */
+                       if (!priv->scan_request->ssids[i].ssid_len)
+                               continue;
+                       scan->direct_scan[p].id = WLAN_EID_SSID;
+                       scan->direct_scan[p].len =
+                               priv->scan_request->ssids[i].ssid_len;
+                       memcpy(scan->direct_scan[p].ssid,
+                              priv->scan_request->ssids[i].ssid,
+                              priv->scan_request->ssids[i].ssid_len);
+                       n_probes++;
+                       p++;
+               }
+               is_active = true;
        } else
-               IWL_DEBUG_SCAN(priv, "Kicking off one indirect scan.\n");
+               IWL_DEBUG_SCAN(priv, "Kicking off passive scan.\n");
 
        /* We don't build a direct scan probe request; the uCode will do
         * that based on the direct_mask added to each channel entry */
@@ -3361,7 +3149,12 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                band = IEEE80211_BAND_2GHZ;
        } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
                scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
-               scan->good_CRC_th = IWL_GOOD_CRC_TH;
+               /*
+                * If active scaning is requested but a certain channel
+                * is marked passive, we can do active scanning if we
+                * detect transmissions.
+                */
+               scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
                band = IEEE80211_BAND_5GHZ;
        } else {
                IWL_WARN(priv, "Invalid scan band count\n");
@@ -3369,19 +3162,20 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        }
 
        scan->tx_cmd.len = cpu_to_le16(
-               iwl_fill_probe_req(priv, band,
-                                  (struct ieee80211_mgmt *)scan->data,
-                                  IWL_MAX_SCAN_SIZE - sizeof(*scan)));
+                       iwl_fill_probe_req(priv,
+                               (struct ieee80211_mgmt *)scan->data,
+                               priv->scan_request->ie,
+                               priv->scan_request->ie_len,
+                               IWL_MAX_SCAN_SIZE - sizeof(*scan)));
 
        /* select Rx antennas */
        scan->flags |= iwl3945_get_antenna_flags(priv);
 
-       if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
+       if (iwl_is_monitor_mode(priv))
                scan->filter_flags = RXON_FILTER_PROMISC_MSK;
 
        scan->channel_count =
-               iwl3945_get_channels_for_scan(priv, band, 1, /* active */
-                                             n_probes,
+               iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
                        (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
 
        if (scan->channel_count == 0) {
@@ -3458,7 +3252,7 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
 
 #define IWL_DELAY_NEXT_SCAN (HZ*2)
 
-static void iwl3945_post_associate(struct iwl_priv *priv)
+void iwl3945_post_associate(struct iwl_priv *priv)
 {
        int rc = 0;
        struct ieee80211_conf *conf = NULL;
@@ -3483,7 +3277,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv)
        conf = ieee80211_get_hw_conf(priv->hw);
 
        priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       iwl3945_commit_rxon(priv);
+       iwlcore_commit_rxon(priv);
 
        memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
        iwl3945_setup_rxon_timing(priv);
@@ -3516,7 +3310,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv)
 
        }
 
-       iwl3945_commit_rxon(priv);
+       iwlcore_commit_rxon(priv);
 
        switch (priv->iw_mode) {
        case NL80211_IFTYPE_STATION:
@@ -3526,7 +3320,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv)
        case NL80211_IFTYPE_ADHOC:
 
                priv->assoc_id = 1;
-               iwl3945_add_station(priv, priv->bssid, 0, 0);
+               priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 0, 0, NULL);
                iwl3945_sync_sta(priv, IWL_STA_ID,
                                 (priv->band == IEEE80211_BAND_5GHZ) ?
                                 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
@@ -3548,8 +3342,6 @@ static void iwl3945_post_associate(struct iwl_priv *priv)
        priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
 }
 
-static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
-
 /*****************************************************************************
  *
  * mac80211 entry point functions
@@ -3592,9 +3384,6 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
 
        IWL_DEBUG_INFO(priv, "Start UP work.\n");
 
-       if (test_bit(STATUS_IN_SUSPEND, &priv->status))
-               return 0;
-
        /* Wait for START_ALIVE from ucode. Otherwise callbacks from
         * mac80211 will not be run successfully. */
        ret = wait_event_interruptible_timeout(priv->wait_command_queue,
@@ -3673,140 +3462,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
        return NETDEV_TX_OK;
 }
 
-static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
-                                struct ieee80211_if_init_conf *conf)
-{
-       struct iwl_priv *priv = hw->priv;
-       unsigned long flags;
-
-       IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type);
-
-       if (priv->vif) {
-               IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
-               return -EOPNOTSUPP;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->vif = conf->vif;
-       priv->iw_mode = conf->type;
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       mutex_lock(&priv->mutex);
-
-       if (conf->mac_addr) {
-               IWL_DEBUG_MAC80211(priv, "Set: %pM\n", conf->mac_addr);
-               memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
-       }
-
-       if (iwl_is_ready(priv))
-               iwl3945_set_mode(priv, conf->type);
-
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       return 0;
-}
-
-/**
- * iwl3945_mac_config - mac80211 config callback
- *
- * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
- * be set inappropriately and the driver currently sets the hardware up to
- * use it whenever needed.
- */
-static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
-{
-       struct iwl_priv *priv = hw->priv;
-       const struct iwl_channel_info *ch_info;
-       struct ieee80211_conf *conf = &hw->conf;
-       unsigned long flags;
-       int ret = 0;
-
-       mutex_lock(&priv->mutex);
-       IWL_DEBUG_MAC80211(priv, "enter to channel %d\n",
-                               conf->channel->hw_value);
-
-       if (!iwl_is_ready(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-               ret = -EIO;
-               goto out;
-       }
-
-       if (unlikely(!iwl3945_mod_params.disable_hw_scan &&
-                    test_bit(STATUS_SCANNING, &priv->status))) {
-               IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
-               set_bit(STATUS_CONF_PENDING, &priv->status);
-               mutex_unlock(&priv->mutex);
-               return 0;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       ch_info = iwl_get_channel_info(priv, conf->channel->band,
-                                      conf->channel->hw_value);
-       if (!is_channel_valid(ch_info)) {
-               IWL_DEBUG_SCAN(priv,
-                               "Channel %d [%d] is INVALID for this band.\n",
-                               conf->channel->hw_value, conf->channel->band);
-               IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
-               spin_unlock_irqrestore(&priv->lock, flags);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       iwl_set_rxon_channel(priv, conf->channel);
-
-       iwl_set_flags_for_band(priv, conf->channel->band);
-
-       /* The list of supported rates and rate mask can be different
-        * for each phymode; since the phymode may have changed, reset
-        * the rate mask to what mac80211 lists */
-       iwl_set_rate(priv);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-#ifdef IEEE80211_CONF_CHANNEL_SWITCH
-       if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
-               iwl3945_hw_channel_switch(priv, conf->channel);
-               goto out;
-       }
-#endif
-
-       if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - waiting for uCode\n");
-               goto out;
-       }
-
-       if (!conf->radio_enabled) {
-               iwl_radio_kill_sw_disable_radio(priv);
-               IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n");
-               goto out;
-       }
-
-       if (iwl_is_rfkill(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF kill\n");
-               ret = -EIO;
-               goto out;
-       }
-
-       iwl_set_rate(priv);
-
-       if (memcmp(&priv->active_rxon,
-                  &priv->staging_rxon, sizeof(priv->staging_rxon)))
-               iwl3945_commit_rxon(priv);
-       else
-               IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration\n");
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-out:
-       clear_bit(STATUS_CONF_PENDING, &priv->status);
-       mutex_unlock(&priv->mutex);
-       return ret;
-}
-
-static void iwl3945_config_ap(struct iwl_priv *priv)
+void iwl3945_config_ap(struct iwl_priv *priv)
 {
        int rc = 0;
 
@@ -3818,7 +3474,7 @@ static void iwl3945_config_ap(struct iwl_priv *priv)
 
                /* RXON - unassoc (to set timing command) */
                priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-               iwl3945_commit_rxon(priv);
+               iwlcore_commit_rxon(priv);
 
                /* RXON Timing */
                memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
@@ -3854,8 +3510,8 @@ static void iwl3945_config_ap(struct iwl_priv *priv)
                }
                /* restore RXON assoc */
                priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
-               iwl3945_commit_rxon(priv);
-               iwl3945_add_station(priv, iwl_bcast_addr, 0, 0);
+               iwlcore_commit_rxon(priv);
+               priv->cfg->ops->smgmt->add_station(priv, iwl_bcast_addr, 0, 0, NULL);
        }
        iwl3945_send_beacon_cmd(priv);
 
@@ -3864,189 +3520,6 @@ static void iwl3945_config_ap(struct iwl_priv *priv)
         * clear sta table, add BCAST sta... */
 }
 
-static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
-                                       struct ieee80211_vif *vif,
-                                       struct ieee80211_if_conf *conf)
-{
-       struct iwl_priv *priv = hw->priv;
-       int rc;
-
-       if (conf == NULL)
-               return -EIO;
-
-       if (priv->vif != vif) {
-               IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n");
-               return 0;
-       }
-
-       /* handle this temporarily here */
-       if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
-           conf->changed & IEEE80211_IFCC_BEACON) {
-               struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
-               if (!beacon)
-                       return -ENOMEM;
-               mutex_lock(&priv->mutex);
-               rc = iwl3945_mac_beacon_update(hw, beacon);
-               mutex_unlock(&priv->mutex);
-               if (rc)
-                       return rc;
-       }
-
-       if (!iwl_is_alive(priv))
-               return -EAGAIN;
-
-       mutex_lock(&priv->mutex);
-
-       if (conf->bssid)
-               IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid);
-
-/*
- * very dubious code was here; the probe filtering flag is never set:
- *
-       if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
-           !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
- */
-
-       if (priv->iw_mode == NL80211_IFTYPE_AP) {
-               if (!conf->bssid) {
-                       conf->bssid = priv->mac_addr;
-                       memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
-                       IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n",
-                                          conf->bssid);
-               }
-               if (priv->ibss_beacon)
-                       dev_kfree_skb(priv->ibss_beacon);
-
-               priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
-       }
-
-       if (iwl_is_rfkill(priv))
-               goto done;
-
-       if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
-           !is_multicast_ether_addr(conf->bssid)) {
-               /* If there is currently a HW scan going on in the background
-                * then we need to cancel it else the RXON below will fail. */
-               if (iwl_scan_cancel_timeout(priv, 100)) {
-                       IWL_WARN(priv, "Aborted scan still in progress "
-                                   "after 100ms\n");
-                       IWL_DEBUG_MAC80211(priv, "leaving:scan abort failed\n");
-                       mutex_unlock(&priv->mutex);
-                       return -EAGAIN;
-               }
-               memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN);
-
-               /* TODO: Audit driver for usage of these members and see
-                * if mac80211 deprecates them (priv->bssid looks like it
-                * shouldn't be there, but I haven't scanned the IBSS code
-                * to verify) - jpk */
-               memcpy(priv->bssid, conf->bssid, ETH_ALEN);
-
-               if (priv->iw_mode == NL80211_IFTYPE_AP)
-                       iwl3945_config_ap(priv);
-               else {
-                       rc = iwl3945_commit_rxon(priv);
-                       if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
-                               iwl3945_add_station(priv,
-                                       priv->active_rxon.bssid_addr, 1, 0);
-               }
-
-       } else {
-               iwl_scan_cancel_timeout(priv, 100);
-               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-               iwl3945_commit_rxon(priv);
-       }
-
- done:
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       mutex_unlock(&priv->mutex);
-
-       return 0;
-}
-
-static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
-                                    struct ieee80211_if_init_conf *conf)
-{
-       struct iwl_priv *priv = hw->priv;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       mutex_lock(&priv->mutex);
-
-       if (iwl_is_ready_rf(priv)) {
-               iwl_scan_cancel_timeout(priv, 100);
-               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-               iwl3945_commit_rxon(priv);
-       }
-       if (priv->vif == conf->vif) {
-               priv->vif = NULL;
-               memset(priv->bssid, 0, ETH_ALEN);
-       }
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
-#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
-
-static void iwl3945_bss_info_changed(struct ieee80211_hw *hw,
-                                    struct ieee80211_vif *vif,
-                                    struct ieee80211_bss_conf *bss_conf,
-                                    u32 changes)
-{
-       struct iwl_priv *priv = hw->priv;
-
-       IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
-
-       if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-               IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
-                                  bss_conf->use_short_preamble);
-               if (bss_conf->use_short_preamble)
-                       priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-               else
-                       priv->staging_rxon.flags &=
-                               ~RXON_FLG_SHORT_PREAMBLE_MSK;
-       }
-
-       if (changes & BSS_CHANGED_ERP_CTS_PROT) {
-               IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n",
-                                  bss_conf->use_cts_prot);
-               if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
-                       priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
-               else
-                       priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
-       }
-
-       if (changes & BSS_CHANGED_ASSOC) {
-               IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
-               /* This should never happen as this function should
-                * never be called from interrupt context. */
-               if (WARN_ON_ONCE(in_interrupt()))
-                       return;
-               if (bss_conf->assoc) {
-                       priv->assoc_id = bss_conf->aid;
-                       priv->beacon_int = bss_conf->beacon_int;
-                       priv->timestamp = bss_conf->timestamp;
-                       priv->assoc_capability = bss_conf->assoc_capability;
-                       priv->power_data.dtim_period = bss_conf->dtim_period;
-                       priv->next_scan_jiffies = jiffies +
-                                       IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
-                       mutex_lock(&priv->mutex);
-                       iwl3945_post_associate(priv);
-                       mutex_unlock(&priv->mutex);
-               } else {
-                       priv->assoc_id = 0;
-                       IWL_DEBUG_MAC80211(priv,
-                                       "DISASSOC %d\n", bss_conf->assoc);
-               }
-       } else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
-                       IWL_DEBUG_MAC80211(priv,
-                                       "Associated Changes %d\n", changes);
-                       iwl3945_send_rxon_assoc(priv);
-       }
-
-}
-
 static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                               struct ieee80211_vif *vif,
                               struct ieee80211_sta *sta,
@@ -4069,9 +3542,9 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        static_key = !iwl_is_associated(priv);
 
        if (!static_key) {
-               sta_id = iwl3945_hw_find_station(priv, addr);
+               sta_id = priv->cfg->ops->smgmt->find_station(priv, addr);
                if (sta_id == IWL_INVALID_STATION) {
-                       IWL_DEBUG_MAC80211(priv, "leave - %pMnot in station map.\n",
+                       IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
                                            addr);
                        return -EINVAL;
                }
@@ -4105,185 +3578,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        return ret;
 }
 
-static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
-                          const struct ieee80211_tx_queue_params *params)
-{
-       struct iwl_priv *priv = hw->priv;
-       unsigned long flags;
-       int q;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (!iwl_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-               return -EIO;
-       }
-
-       if (queue >= AC_NUM) {
-               IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue);
-               return 0;
-       }
-
-       q = AC_NUM - 1 - queue;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min);
-       priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
-       priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
-       priv->qos_data.def_qos_parm.ac[q].edca_txop =
-                       cpu_to_le16((params->txop * 32));
-
-       priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
-       priv->qos_data.qos_active = 1;
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       mutex_lock(&priv->mutex);
-       if (priv->iw_mode == NL80211_IFTYPE_AP)
-               iwl_activate_qos(priv, 1);
-       else if (priv->assoc_id && iwl_is_associated(priv))
-               iwl_activate_qos(priv, 0);
-
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       return 0;
-}
-
-static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw,
-                               struct ieee80211_tx_queue_stats *stats)
-{
-       struct iwl_priv *priv = hw->priv;
-       int i, avail;
-       struct iwl_tx_queue *txq;
-       struct iwl_queue *q;
-       unsigned long flags;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (!iwl_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-               return -EIO;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       for (i = 0; i < AC_NUM; i++) {
-               txq = &priv->txq[i];
-               q = &txq->q;
-               avail = iwl_queue_space(q);
-
-               stats[i].len = q->n_window - avail;
-               stats[i].limit = q->n_window - q->high_mark;
-               stats[i].count = q->n_window;
-
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-       return 0;
-}
-
-static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
-{
-       struct iwl_priv *priv = hw->priv;
-       unsigned long flags;
-
-       mutex_lock(&priv->mutex);
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       iwl_reset_qos(priv);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->assoc_id = 0;
-       priv->assoc_capability = 0;
-
-       /* new association get rid of ibss beacon skb */
-       if (priv->ibss_beacon)
-               dev_kfree_skb(priv->ibss_beacon);
-
-       priv->ibss_beacon = NULL;
-
-       priv->beacon_int = priv->hw->conf.beacon_int;
-       priv->timestamp = 0;
-       if ((priv->iw_mode == NL80211_IFTYPE_STATION))
-               priv->beacon_int = 0;
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (!iwl_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-               mutex_unlock(&priv->mutex);
-               return;
-       }
-
-       /* we are restarting association process
-        * clear RXON_FILTER_ASSOC_MSK bit
-       */
-       if (priv->iw_mode != NL80211_IFTYPE_AP) {
-               iwl_scan_cancel_timeout(priv, 100);
-               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-               iwl3945_commit_rxon(priv);
-       }
-
-       /* Per mac80211.h: This is only used in IBSS mode... */
-       if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
-
-               IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n");
-               mutex_unlock(&priv->mutex);
-               return;
-       }
-
-       iwl_set_rate(priv);
-
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-}
-
-static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-       struct iwl_priv *priv = hw->priv;
-       unsigned long flags;
-       __le64 timestamp;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (!iwl_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-               return -EIO;
-       }
-
-       if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
-               IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n");
-               return -EIO;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       if (priv->ibss_beacon)
-               dev_kfree_skb(priv->ibss_beacon);
-
-       priv->ibss_beacon = skb;
-
-       priv->assoc_id = 0;
-       timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
-       priv->timestamp = le64_to_cpu(timestamp);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       iwl_reset_qos(priv);
-
-       iwl3945_post_associate(priv);
-
-
-       return 0;
-}
-
 /*****************************************************************************
  *
  * sysfs attributes
@@ -4391,7 +3685,7 @@ static ssize_t store_flags(struct device *d,
                        IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
                                       flags);
                        priv->staging_rxon.flags = cpu_to_le32(flags);
-                       iwl3945_commit_rxon(priv);
+                       iwlcore_commit_rxon(priv);
                }
        }
        mutex_unlock(&priv->mutex);
@@ -4427,7 +3721,7 @@ static ssize_t store_filter_flags(struct device *d,
                                       "0x%04X\n", filter_flags);
                        priv->staging_rxon.filter_flags =
                                cpu_to_le32(filter_flags);
-                       iwl3945_commit_rxon(priv);
+                       iwlcore_commit_rxon(priv);
                }
        }
        mutex_unlock(&priv->mutex);
@@ -4546,11 +3840,6 @@ static ssize_t store_power_level(struct device *d,
 
        mutex_lock(&priv->mutex);
 
-       if (!iwl_is_ready(priv)) {
-               ret = -EAGAIN;
-               goto out;
-       }
-
        ret = strict_strtoul(buf, 10, &mode);
        if (ret)
                goto out;
@@ -4812,16 +4101,16 @@ static struct ieee80211_ops iwl3945_hw_ops = {
        .tx = iwl3945_mac_tx,
        .start = iwl3945_mac_start,
        .stop = iwl3945_mac_stop,
-       .add_interface = iwl3945_mac_add_interface,
-       .remove_interface = iwl3945_mac_remove_interface,
-       .config = iwl3945_mac_config,
-       .config_interface = iwl3945_mac_config_interface,
+       .add_interface = iwl_mac_add_interface,
+       .remove_interface = iwl_mac_remove_interface,
+       .config = iwl_mac_config,
+       .config_interface = iwl_mac_config_interface,
        .configure_filter = iwl_configure_filter,
        .set_key = iwl3945_mac_set_key,
-       .get_tx_stats = iwl3945_mac_get_tx_stats,
-       .conf_tx = iwl3945_mac_conf_tx,
-       .reset_tsf = iwl3945_mac_reset_tsf,
-       .bss_info_changed = iwl3945_bss_info_changed,
+       .get_tx_stats = iwl_mac_get_tx_stats,
+       .conf_tx = iwl_mac_conf_tx,
+       .reset_tsf = iwl_mac_reset_tsf,
+       .bss_info_changed = iwl_bss_info_changed,
        .hw_scan = iwl_mac_hw_scan
 };
 
@@ -4843,7 +4132,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
        mutex_init(&priv->mutex);
 
        /* Clear the driver's (not device's) station table */
-       iwl3945_clear_stations_table(priv);
+       priv->cfg->ops->smgmt->clear_station_table(priv);
 
        priv->data_retry_limit = -1;
        priv->ieee_channels = NULL;
@@ -4905,7 +4194,8 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
 
        /* Tell mac80211 our characteristics */
        hw->flags = IEEE80211_HW_SIGNAL_DBM |
-                   IEEE80211_HW_NOISE_DBM;
+                   IEEE80211_HW_NOISE_DBM |
+                   IEEE80211_HW_SPECTRUM_MGMT;
 
        hw->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_STATION) |
@@ -4913,6 +4203,10 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
 
        hw->wiphy->custom_regulatory = true;
 
+       hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
+       /* we create the 802.11 header and a zero-length SSID element */
+       hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
+
        /* Default value; 4 EDCA QOS priorities */
        hw->queues = 4;
 
@@ -4998,9 +4292,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        pci_set_master(pdev);
 
-       err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
        if (!err)
-               err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
        if (err) {
                IWL_WARN(priv, "No suitable DMA available.\n");
                goto out_pci_disable_device;
@@ -5073,20 +4367,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n",
                priv->cfg->name);
 
-       /***********************************
-        * 7. Initialize Module Parameters
-        * **********************************/
-
-       /* Initialize module parameter values here */
-       /* Disable radio (SW RF KILL) via parameter when loading driver */
-       if (iwl3945_mod_params.disable) {
-               set_bit(STATUS_RF_KILL_SW, &priv->status);
-               IWL_DEBUG_INFO(priv, "Radio disabled.\n");
-       }
-
-
        /***********************
-        * 8. Setup Services
+        * 7. Setup Services
         * ********************/
 
        spin_lock_irqsave(&priv->lock, flags);
@@ -5114,7 +4396,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        iwl3945_setup_rx_handlers(priv);
 
        /*********************************
-        * 9. Setup and Register mac80211
+        * 8. Setup and Register mac80211
         * *******************************/
 
        iwl_enable_interrupts(priv);
@@ -5123,6 +4405,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        if (err)
                goto  out_remove_sysfs;
 
+       err = iwl_dbgfs_register(priv, DRV_NAME);
+       if (err)
+               IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
+
        err = iwl_rfkill_init(priv);
        if (err)
                IWL_ERR(priv, "Unable to initialize RFKILL system. "
@@ -5173,6 +4459,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
        IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
+       iwl_dbgfs_unregister(priv);
+
        set_bit(STATUS_EXIT_PENDING, &priv->status);
 
        if (priv->mac80211_registered) {
@@ -5194,16 +4482,16 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
        sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
        iwl_rfkill_unregister(priv);
-       cancel_delayed_work(&priv->rfkill_poll);
+       cancel_delayed_work_sync(&priv->rfkill_poll);
 
        iwl3945_dealloc_ucode_pci(priv);
 
        if (priv->rxq.bd)
-               iwl_rx_queue_free(priv, &priv->rxq);
+               iwl3945_rx_queue_free(priv, &priv->rxq);
        iwl3945_hw_txq_ctx_free(priv);
 
        iwl3945_unset_hw_params(priv);
-       iwl3945_clear_stations_table(priv);
+       priv->cfg->ops->smgmt->clear_station_table(priv);
 
        /*netif_stop_queue(dev); */
        flush_workqueue(priv->workqueue);
@@ -5231,43 +4519,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
        ieee80211_free_hw(priv->hw);
 }
 
-#ifdef CONFIG_PM
-
-static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-
-       if (priv->is_open) {
-               set_bit(STATUS_IN_SUSPEND, &priv->status);
-               iwl3945_mac_stop(priv->hw);
-               priv->is_open = 1;
-       }
-       pci_save_state(pdev);
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, PCI_D3hot);
-
-       return 0;
-}
-
-static int iwl3945_pci_resume(struct pci_dev *pdev)
-{
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-       int ret;
-
-       pci_set_power_state(pdev, PCI_D0);
-       ret = pci_enable_device(pdev);
-       if (ret)
-               return ret;
-       pci_restore_state(pdev);
-
-       if (priv->is_open)
-               iwl3945_mac_start(priv->hw);
-
-       clear_bit(STATUS_IN_SUSPEND, &priv->status);
-       return 0;
-}
-
-#endif /* CONFIG_PM */
 
 /*****************************************************************************
  *
@@ -5281,8 +4532,8 @@ static struct pci_driver iwl3945_driver = {
        .probe = iwl3945_pci_probe,
        .remove = __devexit_p(iwl3945_pci_remove),
 #ifdef CONFIG_PM
-       .suspend = iwl3945_pci_suspend,
-       .resume = iwl3945_pci_resume,
+       .suspend = iwl_pci_suspend,
+       .resume = iwl_pci_resume,
 #endif
 };
 
@@ -5323,8 +4574,6 @@ MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
 
 module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444);
 MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(disable, iwl3945_mod_params.disable, int, 0444);
-MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
 module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444);
 MODULE_PARM_DESC(swcrypto,
                 "using software crypto (default 1 [software])\n");