Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-2.6.git] / drivers / net / wireless / iwlwifi / iwl-agn.c
index 5d2bd88..7e6c463 100644 (file)
@@ -32,8 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -49,8 +47,6 @@
 
 #include <asm/div64.h>
 
-#define DRV_NAME        "iwlagn"
-
 #include "iwl-eeprom.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
@@ -59,7 +55,8 @@
 #include "iwl-sta.h"
 #include "iwl-agn-calib.h"
 #include "iwl-agn.h"
-
+#include "iwl-pci.h"
+#include "iwl-trans.h"
 
 /******************************************************************************
  *
@@ -93,12 +90,10 @@ void iwl_update_chain_flags(struct iwl_priv *priv)
 {
        struct iwl_rxon_context *ctx;
 
-       if (priv->cfg->ops->hcmd->set_rxon_chain) {
-               for_each_context(priv, ctx) {
-                       priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-                       if (ctx->active.rx_chain != ctx->staging.rx_chain)
-                               iwlcore_commit_rxon(priv, ctx);
-               }
+       for_each_context(priv, ctx) {
+               iwlagn_set_rxon_chain(priv, ctx);
+               if (ctx->active.rx_chain != ctx->staging.rx_chain)
+                       iwlagn_commit_rxon(priv, ctx);
        }
 }
 
@@ -135,6 +130,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
        struct iwl_host_cmd cmd = {
                .id = REPLY_TX_BEACON,
        };
+       struct ieee80211_tx_info *info;
        u32 frame_size;
        u32 rate_flags;
        u32 rate;
@@ -175,14 +171,31 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
                           frame_size);
 
        /* Set up packet rate and flags */
-       rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx);
+       info = IEEE80211_SKB_CB(priv->beacon_skb);
+
+       /*
+        * Let's set up the rate at least somewhat correctly;
+        * it will currently not actually be used by the uCode,
+        * it uses the broadcast station's rate instead.
+        */
+       if (info->control.rates[0].idx < 0 ||
+           info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
+               rate = 0;
+       else
+               rate = info->control.rates[0].idx;
+
        priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
                                              priv->hw_params.valid_tx_ant);
        rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
-       if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE))
+
+       /* In mac80211, rates for 5 GHz start at 0 */
+       if (info->band == IEEE80211_BAND_5GHZ)
+               rate += IWL_FIRST_OFDM_RATE;
+       else if (rate >= IWL_FIRST_CCK_RATE && rate <= IWL_LAST_CCK_RATE)
                rate_flags |= RATE_MCS_CCK_MSK;
-       tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate,
-                       rate_flags);
+
+       tx_beacon_cmd->tx.rate_n_flags =
+                       iwl_hw_set_rate_n_flags(rate, rate_flags);
 
        /* Submit command */
        cmd.len[0] = sizeof(*tx_beacon_cmd);
@@ -245,7 +258,7 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work)
        /* dont send host command if rf-kill is on */
        if (!iwl_is_ready_rf(priv))
                return;
-       priv->cfg->ops->hcmd->send_bt_config(priv);
+       iwlagn_send_advance_bt_config(priv);
 }
 
 static void iwl_bg_bt_full_concurrency(struct work_struct *work)
@@ -272,12 +285,11 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
         * to avoid 3-wire collisions
         */
        for_each_context(priv, ctx) {
-               if (priv->cfg->ops->hcmd->set_rxon_chain)
-                       priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-               iwlcore_commit_rxon(priv, ctx);
+               iwlagn_set_rxon_chain(priv, ctx);
+               iwlagn_commit_rxon(priv, ctx);
        }
 
-       priv->cfg->ops->hcmd->send_bt_config(priv);
+       iwlagn_send_advance_bt_config(priv);
 out:
        mutex_unlock(&priv->mutex);
 }
@@ -440,10 +452,8 @@ static void iwl_bg_tx_flush(struct work_struct *work)
        if (!iwl_is_ready_rf(priv))
                return;
 
-       if (priv->cfg->ops->lib->txfifo_flush) {
-               IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
-               iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
-       }
+       IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
+       iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
 }
 
 /**
@@ -497,9 +507,9 @@ static void iwl_rx_handle(struct iwl_priv *priv)
 
                rxq->queue[i] = NULL;
 
-               pci_unmap_page(priv->pci_dev, rxb->page_dma,
+               dma_unmap_page(priv->bus.dev, rxb->page_dma,
                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                              PCI_DMA_FROMDEVICE);
+                              DMA_FROM_DEVICE);
                pkt = rxb_addr(rxb);
 
                len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
@@ -581,9 +591,9 @@ static void iwl_rx_handle(struct iwl_priv *priv)
                 * rx_free list for reuse later. */
                spin_lock_irqsave(&rxq->lock, flags);
                if (rxb->page != NULL) {
-                       rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
+                       rxb->page_dma = dma_map_page(priv->bus.dev, rxb->page,
                                0, PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
+                               DMA_FROM_DEVICE);
                        list_add_tail(&rxb->list, &rxq->rx_free);
                        rxq->free_count++;
                } else
@@ -939,22 +949,28 @@ static struct attribute_group iwl_attribute_group = {
  *
  ******************************************************************************/
 
-static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
+static void iwl_free_fw_desc(struct iwl_priv *priv, struct fw_desc *desc)
 {
        if (desc->v_addr)
-               dma_free_coherent(&pci_dev->dev, desc->len,
+               dma_free_coherent(priv->bus.dev, desc->len,
                                  desc->v_addr, desc->p_addr);
        desc->v_addr = NULL;
        desc->len = 0;
 }
 
-static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img)
+static void iwl_free_fw_img(struct iwl_priv *priv, struct fw_img *img)
+{
+       iwl_free_fw_desc(priv, &img->code);
+       iwl_free_fw_desc(priv, &img->data);
+}
+
+static void iwl_dealloc_ucode(struct iwl_priv *priv)
 {
-       iwl_free_fw_desc(pci_dev, &img->code);
-       iwl_free_fw_desc(pci_dev, &img->data);
+       iwl_free_fw_img(priv, &priv->ucode_rt);
+       iwl_free_fw_img(priv, &priv->ucode_init);
 }
 
-static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
+static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc,
                             const void *data, size_t len)
 {
        if (!len) {
@@ -962,21 +978,16 @@ static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
                return -EINVAL;
        }
 
-       desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len,
+       desc->v_addr = dma_alloc_coherent(priv->bus.dev, len,
                                          &desc->p_addr, GFP_KERNEL);
        if (!desc->v_addr)
                return -ENOMEM;
+
        desc->len = len;
        memcpy(desc->v_addr, data, len);
        return 0;
 }
 
-static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
-{
-       iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt);
-       iwl_free_fw_img(priv->pci_dev, &priv->ucode_init);
-}
-
 struct iwlagn_ucode_capabilities {
        u32 max_probe_length;
        u32 standard_phy_calibration_size;
@@ -1021,8 +1032,8 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
                       priv->firmware_name);
 
        return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
-                                      &priv->pci_dev->dev, GFP_KERNEL, priv,
-                                      iwl_ucode_callback);
+                                      priv->bus.dev,
+                                      GFP_KERNEL, priv, iwl_ucode_callback);
 }
 
 struct iwlagn_firmware_pieces {
@@ -1443,19 +1454,19 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        /* Runtime instructions and 2 copies of data:
         * 1) unmodified from disk
         * 2) backup cache for save/restore during power-downs */
-       if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code,
+       if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.code,
                              pieces.inst, pieces.inst_size))
                goto err_pci_alloc;
-       if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data,
+       if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.data,
                              pieces.data, pieces.data_size))
                goto err_pci_alloc;
 
        /* Initialization instructions and data */
        if (pieces.init_size && pieces.init_data_size) {
-               if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code,
+               if (iwl_alloc_fw_desc(priv, &priv->ucode_init.code,
                                      pieces.init, pieces.init_size))
                        goto err_pci_alloc;
-               if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data,
+               if (iwl_alloc_fw_desc(priv, &priv->ucode_init.data,
                                      pieces.init_data, pieces.init_data_size))
                        goto err_pci_alloc;
        }
@@ -1485,7 +1496,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        priv->new_scan_threshold_behaviour =
                !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
 
-       if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
+       if ((priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE) &&
+           (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) {
                priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
                priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
        } else
@@ -1523,7 +1535,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        if (err)
                IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
-       err = sysfs_create_group(&priv->pci_dev->dev.kobj,
+       err = sysfs_create_group(&(priv->bus.dev->kobj),
                                        &iwl_attribute_group);
        if (err) {
                IWL_ERR(priv, "failed to create sysfs device attributes\n");
@@ -1544,10 +1556,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 
  err_pci_alloc:
        IWL_ERR(priv, "failed to allocate pci memory\n");
-       iwl_dealloc_ucode_pci(priv);
+       iwl_dealloc_ucode(priv);
  out_unbind:
        complete(&priv->_agn.firmware_loading_complete);
-       device_release_driver(&priv->pci_dev->dev);
+       device_release_driver(priv->bus.dev);
        release_firmware(ucode_raw);
 }
 
@@ -1626,7 +1638,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
        struct iwl_error_event_table table;
 
        base = priv->device_pointers.error_event_table;
-       if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+       if (priv->ucode_type == IWL_UCODE_INIT) {
                if (!base)
                        base = priv->_agn.init_errlog_ptr;
        } else {
@@ -1638,7 +1650,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
                IWL_ERR(priv,
                        "Not valid error log pointer 0x%08X for %s uCode\n",
                        base,
-                       (priv->ucode_type == UCODE_SUBTYPE_INIT)
+                       (priv->ucode_type == IWL_UCODE_INIT)
                                        ? "Init" : "RT");
                return;
        }
@@ -1702,7 +1714,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
                return pos;
 
        base = priv->device_pointers.log_event_table;
-       if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+       if (priv->ucode_type == IWL_UCODE_INIT) {
                if (!base)
                        base = priv->_agn.init_evtlog_ptr;
        } else {
@@ -1815,7 +1827,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
        size_t bufsz = 0;
 
        base = priv->device_pointers.log_event_table;
-       if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+       if (priv->ucode_type == IWL_UCODE_INIT) {
                logsize = priv->_agn.init_evtlog_size;
                if (!base)
                        base = priv->_agn.init_evtlog_ptr;
@@ -1829,7 +1841,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
                IWL_ERR(priv,
                        "Invalid event log pointer 0x%08X for %s uCode\n",
                        base,
-                       (priv->ucode_type == UCODE_SUBTYPE_INIT)
+                       (priv->ucode_type == IWL_UCODE_INIT)
                                        ? "Init" : "RT");
                return -EINVAL;
        }
@@ -2002,7 +2014,7 @@ int iwl_alive_start(struct iwl_priv *priv)
                priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
                priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
                priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
-               priv->cfg->ops->hcmd->send_bt_config(priv);
+               iwlagn_send_advance_bt_config(priv);
                priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
                iwlagn_send_prio_tbl(priv);
 
@@ -2015,7 +2027,13 @@ int iwl_alive_start(struct iwl_priv *priv)
                                         BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
                if (ret)
                        return ret;
+       } else {
+               /*
+                * default is 2-wire BT coexexistence support
+                */
+               iwl_send_bt_config(priv);
        }
+
        if (priv->hw_params.calib_rt_cfg)
                iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
 
@@ -2024,8 +2042,7 @@ int iwl_alive_start(struct iwl_priv *priv)
        priv->active_rate = IWL_RATES_MASK;
 
        /* Configure Tx antenna selection based on H/W config */
-       if (priv->cfg->ops->hcmd->set_tx_ant)
-               priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant);
+       iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant);
 
        if (iwl_is_associated_ctx(ctx)) {
                struct iwl_rxon_cmd *active_rxon =
@@ -2039,16 +2056,7 @@ int iwl_alive_start(struct iwl_priv *priv)
                for_each_context(priv, tmp)
                        iwl_connection_init_rx_config(priv, tmp);
 
-               if (priv->cfg->ops->hcmd->set_rxon_chain)
-                       priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-       }
-
-       if (!priv->cfg->bt_params || (priv->cfg->bt_params &&
-           !priv->cfg->bt_params->advanced_bt_coexist)) {
-               /*
-                * default is 2-wire BT coexexistence support
-                */
-               priv->cfg->ops->hcmd->send_bt_config(priv);
+               iwlagn_set_rxon_chain(priv, ctx);
        }
 
        iwl_reset_run_time_calib(priv);
@@ -2056,7 +2064,7 @@ int iwl_alive_start(struct iwl_priv *priv)
        set_bit(STATUS_READY, &priv->status);
 
        /* Configure the adapter for unassociated operation */
-       ret = iwlcore_commit_rxon(priv, ctx);
+       ret = iwlagn_commit_rxon(priv, ctx);
        if (ret)
                return ret;
 
@@ -2210,8 +2218,7 @@ static int __iwl_up(struct iwl_priv *priv)
 
        ret = iwlagn_load_ucode_wait_alive(priv,
                                           &priv->ucode_rt,
-                                          UCODE_SUBTYPE_REGULAR,
-                                          UCODE_SUBTYPE_REGULAR_NEW);
+                                          IWL_UCODE_REGULAR);
        if (ret) {
                IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
                goto error;
@@ -2516,7 +2523,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
        hw->flags |= IEEE80211_HW_SUPPORTS_PS |
                     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
-       if (priv->cfg->sku & IWL_SKU_N)
+       if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
                hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
                             IEEE80211_HW_SUPPORTS_STATIC_SMPS;
 
@@ -2533,11 +2540,11 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
 
        BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
 
-       if (hw->wiphy->interface_modes & NL80211_IFTYPE_P2P_CLIENT) {
+       if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) {
                hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p;
                hw->wiphy->n_iface_combinations =
                        ARRAY_SIZE(iwlagn_iface_combinations_p2p);
-       } else if (hw->wiphy->interface_modes & NL80211_IFTYPE_AP) {
+       } else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
                hw->wiphy->iface_combinations = iwlagn_iface_combinations_dualmode;
                hw->wiphy->n_iface_combinations =
                        ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
@@ -2549,11 +2556,10 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
                            WIPHY_FLAG_DISABLE_BEACON_HINTS |
                            WIPHY_FLAG_IBSS_RSN;
 
-       /*
-        * For now, disable PS by default because it affects
-        * RX performance significantly.
-        */
-       hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+       if (iwlagn_mod_params.power_save)
+               hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+       else
+               hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
        hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
        /* we create the 802.11 header and a zero-length SSID element */
@@ -2757,7 +2763,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
        IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
                     sta->addr, tid);
 
-       if (!(priv->cfg->sku & IWL_SKU_N))
+       if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE))
                return -EACCES;
 
        mutex_lock(&priv->mutex);
@@ -2916,7 +2922,6 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
         */
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
        u16 ch;
-       unsigned long flags = 0;
 
        IWL_DEBUG_MAC80211(priv, "enter\n");
 
@@ -2926,73 +2931,73 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
                goto out;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
-           test_bit(STATUS_SCANNING, &priv->status))
+           test_bit(STATUS_SCANNING, &priv->status) ||
+           test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
                goto out;
 
        if (!iwl_is_associated_ctx(ctx))
                goto out;
 
-       /* channel switch in progress */
-       if (priv->switch_rxon.switch_in_progress == true)
+       if (!priv->cfg->ops->lib->set_channel_switch)
                goto out;
 
-       if (priv->cfg->ops->lib->set_channel_switch) {
+       ch = channel->hw_value;
+       if (le16_to_cpu(ctx->active.channel) == ch)
+               goto out;
 
-               ch = channel->hw_value;
-               if (le16_to_cpu(ctx->active.channel) != ch) {
-                       ch_info = iwl_get_channel_info(priv,
-                                                      channel->band,
-                                                      ch);
-                       if (!is_channel_valid(ch_info)) {
-                               IWL_DEBUG_MAC80211(priv, "invalid channel\n");
-                               goto out;
-                       }
-                       spin_lock_irqsave(&priv->lock, flags);
-
-                       priv->current_ht_config.smps = conf->smps_mode;
-
-                       /* Configure HT40 channels */
-                       ctx->ht.enabled = conf_is_ht(conf);
-                       if (ctx->ht.enabled) {
-                               if (conf_is_ht40_minus(conf)) {
-                                       ctx->ht.extension_chan_offset =
-                                               IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-                                       ctx->ht.is_40mhz = true;
-                               } else if (conf_is_ht40_plus(conf)) {
-                                       ctx->ht.extension_chan_offset =
-                                               IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-                                       ctx->ht.is_40mhz = true;
-                               } else {
-                                       ctx->ht.extension_chan_offset =
-                                               IEEE80211_HT_PARAM_CHA_SEC_NONE;
-                                       ctx->ht.is_40mhz = false;
-                               }
-                       } else
-                               ctx->ht.is_40mhz = false;
+       ch_info = iwl_get_channel_info(priv, channel->band, ch);
+       if (!is_channel_valid(ch_info)) {
+               IWL_DEBUG_MAC80211(priv, "invalid channel\n");
+               goto out;
+       }
 
-                       if ((le16_to_cpu(ctx->staging.channel) != ch))
-                               ctx->staging.flags = 0;
+       spin_lock_irq(&priv->lock);
 
-                       iwl_set_rxon_channel(priv, channel, ctx);
-                       iwl_set_rxon_ht(priv, ht_conf);
-                       iwl_set_flags_for_band(priv, ctx, channel->band,
-                                              ctx->vif);
-                       spin_unlock_irqrestore(&priv->lock, flags);
+       priv->current_ht_config.smps = conf->smps_mode;
 
-                       iwl_set_rate(priv);
-                       /*
-                        * at this point, staging_rxon has the
-                        * configuration for channel switch
-                        */
-                       if (priv->cfg->ops->lib->set_channel_switch(priv,
-                                                                   ch_switch))
-                               priv->switch_rxon.switch_in_progress = false;
+       /* Configure HT40 channels */
+       ctx->ht.enabled = conf_is_ht(conf);
+       if (ctx->ht.enabled) {
+               if (conf_is_ht40_minus(conf)) {
+                       ctx->ht.extension_chan_offset =
+                               IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+                       ctx->ht.is_40mhz = true;
+               } else if (conf_is_ht40_plus(conf)) {
+                       ctx->ht.extension_chan_offset =
+                               IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+                       ctx->ht.is_40mhz = true;
+               } else {
+                       ctx->ht.extension_chan_offset =
+                               IEEE80211_HT_PARAM_CHA_SEC_NONE;
+                       ctx->ht.is_40mhz = false;
                }
+       } else
+               ctx->ht.is_40mhz = false;
+
+       if ((le16_to_cpu(ctx->staging.channel) != ch))
+               ctx->staging.flags = 0;
+
+       iwl_set_rxon_channel(priv, channel, ctx);
+       iwl_set_rxon_ht(priv, ht_conf);
+       iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
+
+       spin_unlock_irq(&priv->lock);
+
+       iwl_set_rate(priv);
+       /*
+        * at this point, staging_rxon has the
+        * configuration for channel switch
+        */
+       set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+       priv->switch_channel = cpu_to_le16(ch);
+       if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
+               clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+               priv->switch_channel = 0;
+               ieee80211_chswitch_done(ctx->vif, false);
        }
+
 out:
        mutex_unlock(&priv->mutex);
-       if (!priv->switch_rxon.switch_in_progress)
-               ieee80211_chswitch_done(ctx->vif, false);
        IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
@@ -3053,10 +3058,6 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
        mutex_lock(&priv->mutex);
        IWL_DEBUG_MAC80211(priv, "enter\n");
 
-       /* do not support "flush" */
-       if (!priv->cfg->ops->lib->txfifo_flush)
-               goto done;
-
        if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
                IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
                goto done;
@@ -3072,7 +3073,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
         */
        if (drop) {
                IWL_DEBUG_MAC80211(priv, "send flush command\n");
-               if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
+               if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
                        IWL_ERR(priv, "flush request fail\n");
                        goto done;
                }
@@ -3101,7 +3102,7 @@ static void iwlagn_disable_roc(struct iwl_priv *priv)
 
        priv->_agn.hw_roc_channel = NULL;
 
-       iwlcore_commit_rxon(priv, ctx);
+       iwlagn_commit_rxon(priv, ctx);
 
        ctx->is_active = false;
 }
@@ -3144,7 +3145,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
        priv->_agn.hw_roc_channel = channel;
        priv->_agn.hw_roc_chantype = channel_type;
        priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024);
-       iwlcore_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
+       iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
        queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work,
                           msecs_to_jiffies(duration + 20));
 
@@ -3280,9 +3281,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
        priv->rx_statistics_jiffies = jiffies;
 
        /* Choose which receivers/antennas to use */
-       if (priv->cfg->ops->hcmd->set_rxon_chain)
-               priv->cfg->ops->hcmd->set_rxon_chain(priv,
-                                       &priv->contexts[IWL_RXON_CTX_BSS]);
+       iwlagn_set_rxon_chain(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
 
        iwl_init_scan_params(priv);
 
@@ -3353,14 +3352,11 @@ struct ieee80211_ops iwlagn_hw_ops = {
        .offchannel_tx = iwl_mac_offchannel_tx,
        .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
        CFG80211_TESTMODE_CMD(iwl_testmode_cmd)
+       CFG80211_TESTMODE_DUMP(iwl_testmode_dump)
 };
 
 static u32 iwl_hw_detect(struct iwl_priv *priv)
 {
-       u8 rev_id;
-
-       pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
-       IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
        return iwl_read32(priv, CSR_HW_REV);
 }
 
@@ -3376,7 +3372,7 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
        priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
 
        if (iwlagn_mod_params.disable_11n)
-               priv->cfg->sku &= ~IWL_SKU_N;
+               priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
 
        /* Device-specific setup */
        return priv->cfg->ops->lib->set_hw_params(priv);
@@ -3426,29 +3422,9 @@ out:
        return hw;
 }
 
-static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static void iwl_init_context(struct iwl_priv *priv)
 {
-       int err = 0, i;
-       struct iwl_priv *priv;
-       struct ieee80211_hw *hw;
-       struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
-       unsigned long flags;
-       u16 pci_cmd, num_mac;
-       u32 hw_rev;
-
-       /************************
-        * 1. Allocating HW data
-        ************************/
-
-       hw = iwl_alloc_all(cfg);
-       if (!hw) {
-               err = -ENOMEM;
-               goto out;
-       }
-       priv = hw->priv;
-       /* At this point both hw and priv are allocated. */
-
-       priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED;
+       int i;
 
        /*
         * The default context is always valid,
@@ -3480,8 +3456,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
 
        priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
-       priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING;
-       priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd = REPLY_WIPAN_RXON_ASSOC;
+       priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd =
+               REPLY_WIPAN_RXON_TIMING;
+       priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd =
+               REPLY_WIPAN_RXON_ASSOC;
        priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
        priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
        priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
@@ -3501,12 +3479,43 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
 
        BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+}
 
-       SET_IEEE80211_DEV(hw, &pdev->dev);
+int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
+               struct iwl_cfg *cfg)
+{
+       int err = 0;
+       struct iwl_priv *priv;
+       struct ieee80211_hw *hw;
+       u16 num_mac;
+       u32 hw_rev;
+
+       /************************
+        * 1. Allocating HW data
+        ************************/
+       hw = iwl_alloc_all(cfg);
+       if (!hw) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       priv = hw->priv;
+
+       priv->bus.priv = priv;
+       priv->bus.bus_specific = bus_specific;
+       priv->bus.ops = bus_ops;
+       priv->bus.irq = priv->bus.ops->get_irq(&priv->bus);
+       priv->bus.ops->set_drv_data(&priv->bus, priv);
+       priv->bus.dev = priv->bus.ops->get_dev(&priv->bus);
+
+       iwl_trans_register(&priv->trans);
+
+       /* At this point both hw and priv are allocated. */
+
+       SET_IEEE80211_DEV(hw, priv->bus.dev);
 
        IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
        priv->cfg = cfg;
-       priv->pci_dev = pdev;
        priv->inta_mask = CSR_INI_SET_MASK;
 
        /* is antenna coupling more than 35dB ? */
@@ -3522,52 +3531,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (iwl_alloc_traffic_mem(priv))
                IWL_ERR(priv, "Not enough memory to generate traffic log\n");
 
-       /**************************
-        * 2. Initializing PCI bus
-        **************************/
-       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-                               PCIE_LINK_STATE_CLKPM);
-
-       if (pci_enable_device(pdev)) {
-               err = -ENODEV;
-               goto out_ieee80211_free_hw;
-       }
-
-       pci_set_master(pdev);
-
-       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
-       if (!err)
-               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
-       if (err) {
-               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-               if (!err)
-                       err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-               /* both attempts failed: */
-               if (err) {
-                       IWL_WARN(priv, "No suitable DMA available.\n");
-                       goto out_pci_disable_device;
-               }
-       }
-
-       err = pci_request_regions(pdev, DRV_NAME);
-       if (err)
-               goto out_pci_disable_device;
-
-       pci_set_drvdata(pdev, priv);
-
-
-       /***********************
-        * 3. Read REV register
-        ***********************/
-       priv->hw_base = pci_iomap(pdev, 0, 0);
-       if (!priv->hw_base) {
-               err = -ENODEV;
-               goto out_pci_release_regions;
-       }
-
-       IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
-               (unsigned long long) pci_resource_len(pdev, 0));
-       IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
 
        /* these spin locks will be used in apm_ops.init and EEPROM access
         * we should init now
@@ -3582,17 +3545,17 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         */
        iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 
+       /***********************
+        * 3. Read REV register
+        ***********************/
        hw_rev = iwl_hw_detect(priv);
        IWL_INFO(priv, "Detected %s, REV=0x%X\n",
                priv->cfg->name, hw_rev);
 
-       /* We disable the RETRY_TIMEOUT register (0x41) to keep
-        * PCI Tx retries from interfering with C3 CPU state */
-       pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
-
        if (iwl_prepare_card_hw(priv)) {
+               err = -EIO;
                IWL_WARN(priv, "Failed, HW not ready\n");
-               goto out_iounmap;
+               goto out_free_traffic_mem;
        }
 
        /*****************
@@ -3602,7 +3565,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        err = iwl_eeprom_init(priv, hw_rev);
        if (err) {
                IWL_ERR(priv, "Unable to init EEPROM\n");
-               goto out_iounmap;
+               goto out_free_traffic_mem;
        }
        err = iwl_eeprom_check_version(priv);
        if (err)
@@ -3625,10 +3588,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                priv->hw->wiphy->n_addresses++;
        }
 
+       /* initialize all valid contexts */
+       iwl_init_context(priv);
+
        /************************
         * 5. Setup HW constants
         ************************/
        if (iwl_set_hw_params(priv)) {
+               err = -ENOENT;
                IWL_ERR(priv, "failed to set hw parameters\n");
                goto out_free_eeprom;
        }
@@ -3645,19 +3612,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /********************
         * 7. Setup services
         ********************/
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_disable_interrupts(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       pci_enable_msi(priv->pci_dev);
-
        iwl_alloc_isr_ict(priv);
 
-       err = request_irq(priv->pci_dev->irq, iwl_isr_ict,
-                         IRQF_SHARED, DRV_NAME, priv);
+       err = request_irq(priv->bus.irq, iwl_isr_ict, IRQF_SHARED,
+                         DRV_NAME, priv);
        if (err) {
-               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
-               goto out_disable_msi;
+               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq);
+               goto out_uninit_drv;
        }
 
        iwl_setup_deferred_work(priv);
@@ -3665,16 +3626,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        iwl_testmode_init(priv);
 
        /*********************************************
-        * 8. Enable interrupts and read RFKILL state
+        * 8. Enable interrupts
         *********************************************/
 
-       /* enable rfkill interrupt: hw bug w/a */
-       pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
-       if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
-               pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
-               pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
-       }
-
        iwl_enable_rfkill_int(priv);
 
        /* If platform's RF_KILL switch is NOT set to KILL */
@@ -3700,41 +3654,30 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  out_destroy_workqueue:
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
-       free_irq(priv->pci_dev->irq, priv);
- out_disable_msi:
+       free_irq(priv->bus.irq, priv);
        iwl_free_isr_ict(priv);
-       pci_disable_msi(priv->pci_dev);
+ out_uninit_drv:
        iwl_uninit_drv(priv);
  out_free_eeprom:
        iwl_eeprom_free(priv);
- out_iounmap:
-       pci_iounmap(pdev, priv->hw_base);
- out_pci_release_regions:
-       pci_set_drvdata(pdev, NULL);
-       pci_release_regions(pdev);
- out_pci_disable_device:
-       pci_disable_device(pdev);
- out_ieee80211_free_hw:
+ out_free_traffic_mem:
        iwl_free_traffic_mem(priv);
        ieee80211_free_hw(priv->hw);
  out:
        return err;
 }
 
-static void __devexit iwl_pci_remove(struct pci_dev *pdev)
+void __devexit iwl_remove(struct iwl_priv * priv)
 {
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
        unsigned long flags;
 
-       if (!priv)
-               return;
-
        wait_for_completion(&priv->_agn.firmware_loading_complete);
 
        IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
        iwl_dbgfs_unregister(priv);
-       sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+       sysfs_remove_group(&priv->bus.dev->kobj,
+                          &iwl_attribute_group);
 
        /* ieee80211_unregister_hw call wil cause iwl_mac_stop to
         * to be called and iwl_down since we are removing the device
@@ -3764,10 +3707,9 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 
        iwl_synchronize_irq(priv);
 
-       iwl_dealloc_ucode_pci(priv);
+       iwl_dealloc_ucode(priv);
 
-       if (priv->rxq.bd)
-               iwlagn_rx_queue_free(priv, &priv->rxq);
+       priv->trans.ops->rx_free(priv);
        iwlagn_hw_txq_ctx_free(priv);
 
        iwl_eeprom_free(priv);
@@ -3783,12 +3725,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
        priv->workqueue = NULL;
        iwl_free_traffic_mem(priv);
 
-       free_irq(priv->pci_dev->irq, priv);
-       pci_disable_msi(priv->pci_dev);
-       pci_iounmap(pdev, priv->hw_base);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
+       free_irq(priv->bus.irq, priv);
+       priv->bus.ops->set_drv_data(&priv->bus, NULL);
 
        iwl_uninit_drv(priv);
 
@@ -3805,206 +3743,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
  * driver and module entry point
  *
  *****************************************************************************/
-
-/* Hardware specific file defines the PCI IDs table for that hardware module */
-static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
-       {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
-
-/* 5300 Series WiFi */
-       {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
-
-/* 5350 Series WiFi/WiMax */
-       {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
-
-/* 5150 Series Wifi/WiMax */
-       {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
-
-       {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
-
-/* 6x00 Series */
-       {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
-       {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
-       {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
-       {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
-
-/* 6x05 Series */
-       {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
-
-/* 6x30 Series */
-       {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
-       {IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
-       {IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
-
-/* 6x50 WiFi/WiMax Series */
-       {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
-
-/* 6150 WiFi/WiMax Series */
-       {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0885, 0x1306, iwl6150_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0885, 0x1326, iwl6150_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0886, 0x1316, iwl6150_bgn_cfg)},
-
-/* 1000 Series WiFi */
-       {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
-
-/* 100 Series WiFi */
-       {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
-       {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
-       {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
-
-/* 130 Series WiFi */
-       {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
-
-/* 2x00 Series */
-       {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
-
-/* 2x30 Series */
-       {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
-
-/* 6x35 Series */
-       {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
-
-/* 105 Series */
-       {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)},
-
-/* 135 Series */
-       {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)},
-
-       {0}
-};
-MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
-
-static struct pci_driver iwl_driver = {
-       .name = DRV_NAME,
-       .id_table = iwl_hw_card_ids,
-       .probe = iwl_pci_probe,
-       .remove = __devexit_p(iwl_pci_remove),
-       .driver.pm = IWL_PM_OPS,
-};
-
 static int __init iwl_init(void)
 {
 
@@ -4018,12 +3756,10 @@ static int __init iwl_init(void)
                return ret;
        }
 
-       ret = pci_register_driver(&iwl_driver);
-       if (ret) {
-               pr_err("Unable to initialize PCI module\n");
-               goto error_register;
-       }
+       ret = iwl_pci_register_driver();
 
+       if (ret)
+               goto error_register;
        return ret;
 
 error_register:
@@ -4033,7 +3769,7 @@ error_register:
 
 static void __exit iwl_exit(void)
 {
-       pci_unregister_driver(&iwl_driver);
+       iwl_pci_unregister_driver();
        iwlagn_rate_control_unregister();
 }
 
@@ -4075,3 +3811,51 @@ MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
 
 module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);
 MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");
+
+module_param_named(wd_disable, iwlagn_mod_params.wd_disable, bool, S_IRUGO);
+MODULE_PARM_DESC(wd_disable,
+               "Disable stuck queue watchdog timer (default: 0 [enabled])");
+
+/*
+ * set bt_coex_active to true, uCode will do kill/defer
+ * every time the priority line is asserted (BT is sending signals on the
+ * priority line in the PCIx).
+ * set bt_coex_active to false, uCode will ignore the BT activity and
+ * perform the normal operation
+ *
+ * User might experience transmit issue on some platform due to WiFi/BT
+ * co-exist problem. The possible behaviors are:
+ *   Able to scan and finding all the available AP
+ *   Not able to associate with any AP
+ * On those platforms, WiFi communication can be restored by set
+ * "bt_coex_active" module parameter to "false"
+ *
+ * default: bt_coex_active = true (BT_COEX_ENABLE)
+ */
+module_param_named(bt_coex_active, iwlagn_mod_params.bt_coex_active,
+               bool, S_IRUGO);
+MODULE_PARM_DESC(bt_coex_active, "enable wifi/bt co-exist (default: enable)");
+
+module_param_named(led_mode, iwlagn_mod_params.led_mode, int, S_IRUGO);
+MODULE_PARM_DESC(led_mode, "0=system default, "
+               "1=On(RF On)/Off(RF Off), 2=blinking (default: 0)");
+
+module_param_named(power_save, iwlagn_mod_params.power_save,
+               bool, S_IRUGO);
+MODULE_PARM_DESC(power_save,
+                "enable WiFi power management (default: disable)");
+
+module_param_named(power_level, iwlagn_mod_params.power_level,
+               int, S_IRUGO);
+MODULE_PARM_DESC(power_level,
+                "default power save level (range from 1 - 5, default: 1)");
+
+/*
+ * For now, keep using power level 1 instead of automatically
+ * adjusting ...
+ */
+module_param_named(no_sleep_autoadjust, iwlagn_mod_params.no_sleep_autoadjust,
+               bool, S_IRUGO);
+MODULE_PARM_DESC(no_sleep_autoadjust,
+                "don't automatically adjust sleep level "
+                "according to maximum network latency (default: true)");