iwlwifi: make tx_cmd_pool kmem cache global
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-agn.c
index 3e429a3..7927e3e 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
-#include <linux/firmware.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 
 #include <asm/div64.h>
 
 #include "iwl-eeprom.h"
-#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
 #include "iwl-agn-calib.h"
 #include "iwl-agn.h"
 #include "iwl-shared.h"
-#include "iwl-bus.h"
 #include "iwl-trans.h"
+#include "iwl-op-mode.h"
 
 /******************************************************************************
  *
@@ -134,7 +132,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
         * beacon contents.
         */
 
-       lockdep_assert_held(&priv->shrd->mutex);
+       lockdep_assert_held(&priv->mutex);
 
        if (!priv->beacon_ctx) {
                IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
@@ -199,7 +197,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
        cmd.data[1] = priv->beacon_skb->data;
        cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
 
-       return iwl_trans_send_cmd(trans(priv), &cmd);
+       return iwl_dvm_send_cmd(priv, &cmd);
 }
 
 static void iwl_bg_beacon_update(struct work_struct *work)
@@ -208,7 +206,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
                container_of(work, struct iwl_priv, beacon_update);
        struct sk_buff *beacon;
 
-       mutex_lock(&priv->shrd->mutex);
+       mutex_lock(&priv->mutex);
        if (!priv->beacon_ctx) {
                IWL_ERR(priv, "updating beacon w/o beacon context!\n");
                goto out;
@@ -238,7 +236,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
 
        iwlagn_send_beacon_cmd(priv);
  out:
-       mutex_unlock(&priv->shrd->mutex);
+       mutex_unlock(&priv->mutex);
 }
 
 static void iwl_bg_bt_runtime_config(struct work_struct *work)
@@ -261,7 +259,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
                container_of(work, struct iwl_priv, bt_full_concurrency);
        struct iwl_rxon_context *ctx;
 
-       mutex_lock(&priv->shrd->mutex);
+       mutex_lock(&priv->mutex);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
                goto out;
@@ -285,7 +283,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
 
        iwlagn_send_advance_bt_config(priv);
 out:
-       mutex_unlock(&priv->shrd->mutex);
+       mutex_unlock(&priv->mutex);
 }
 
 /**
@@ -328,15 +326,14 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
                ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
 
        /* Make sure device is powered up for SRAM reads */
-       spin_lock_irqsave(&bus(priv)->reg_lock, reg_flags);
-       if (iwl_grab_nic_access(bus(priv))) {
-               spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags);
+       spin_lock_irqsave(&trans(priv)->reg_lock, reg_flags);
+       if (unlikely(!iwl_grab_nic_access(trans(priv)))) {
+               spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags);
                return;
        }
 
        /* Set starting address; reads will auto-increment */
-       iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr);
-       rmb();
+       iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, ptr);
 
        /*
         * Refuse to read more than would have fit into the log from
@@ -352,19 +349,20 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
         * place event id # at far right for easier visual parsing.
         */
        for (i = 0; i < num_events; i++) {
-               ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
-               time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
+               ev = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
+               time = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
                if (mode == 0) {
-                       trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev);
+                       trace_iwlwifi_dev_ucode_cont_event(
+                                       trans(priv)->dev, 0, time, ev);
                } else {
-                       data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
-                       trace_iwlwifi_dev_ucode_cont_event(priv, time,
-                                                          data, ev);
+                       data = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
+                       trace_iwlwifi_dev_ucode_cont_event(
+                                       trans(priv)->dev, time, data, ev);
                }
        }
        /* Allow device to power down */
-       iwl_release_nic_access(bus(priv));
-       spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags);
+       iwl_release_nic_access(trans(priv));
+       spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags);
 }
 
 static void iwl_continuous_event_trace(struct iwl_priv *priv)
@@ -383,7 +381,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
 
        base = priv->shrd->device_pointers.log_event_table;
        if (iwlagn_hw_valid_rtc_data_addr(base)) {
-               iwl_read_targ_mem_words(bus(priv), base, &read, sizeof(read));
+               iwl_read_targ_mem_words(trans(priv), base, &read, sizeof(read));
 
                capacity = read.capacity;
                mode = read.mode;
@@ -424,7 +422,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
                else
                        priv->event_log.wraps_once_count++;
 
-               trace_iwlwifi_dev_ucode_wrap_event(priv,
+               trace_iwlwifi_dev_ucode_wrap_event(trans(priv)->dev,
                                num_wraps - priv->event_log.num_wraps,
                                next_entry, priv->event_log.next_entry);
 
@@ -490,7 +488,7 @@ static void iwl_bg_tx_flush(struct work_struct *work)
        iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
 }
 
-static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
+void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
 {
        int i;
 
@@ -513,6 +511,7 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
        priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
        priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
        priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
+       priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
        priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
                BIT(NL80211_IFTYPE_ADHOC);
        priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
@@ -547,620 +546,15 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
        BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
 }
 
-static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
-
-#define UCODE_EXPERIMENTAL_INDEX       100
-#define UCODE_EXPERIMENTAL_TAG         "exp"
-
-static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
-{
-       const char *name_pre = cfg(priv)->fw_name_pre;
-       char tag[8];
-
-       if (first) {
-#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
-               priv->fw_index = UCODE_EXPERIMENTAL_INDEX;
-               strcpy(tag, UCODE_EXPERIMENTAL_TAG);
-       } else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) {
-#endif
-               priv->fw_index = cfg(priv)->ucode_api_max;
-               sprintf(tag, "%d", priv->fw_index);
-       } else {
-               priv->fw_index--;
-               sprintf(tag, "%d", priv->fw_index);
-       }
-
-       if (priv->fw_index < cfg(priv)->ucode_api_min) {
-               IWL_ERR(priv, "no suitable firmware found!\n");
-               return -ENOENT;
-       }
-
-       sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
-
-       IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n",
-                      (priv->fw_index == UCODE_EXPERIMENTAL_INDEX)
-                               ? "EXPERIMENTAL " : "",
-                      priv->firmware_name);
-
-       return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
-                                      bus(priv)->dev,
-                                      GFP_KERNEL, priv, iwl_ucode_callback);
-}
-
-struct iwlagn_firmware_pieces {
-       const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data;
-       size_t inst_size, data_size, init_size, init_data_size,
-              wowlan_inst_size, wowlan_data_size;
-
-       u32 build;
-
-       u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
-       u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
-};
-
-static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
-                                      const struct firmware *ucode_raw,
-                                      struct iwlagn_firmware_pieces *pieces)
-{
-       struct iwl_ucode_header *ucode = (void *)ucode_raw->data;
-       u32 api_ver, hdr_size;
-       const u8 *src;
-
-       priv->ucode_ver = le32_to_cpu(ucode->ver);
-       api_ver = IWL_UCODE_API(priv->ucode_ver);
-
-       switch (api_ver) {
-       default:
-               hdr_size = 28;
-               if (ucode_raw->size < hdr_size) {
-                       IWL_ERR(priv, "File size too small!\n");
-                       return -EINVAL;
-               }
-               pieces->build = le32_to_cpu(ucode->u.v2.build);
-               pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size);
-               pieces->data_size = le32_to_cpu(ucode->u.v2.data_size);
-               pieces->init_size = le32_to_cpu(ucode->u.v2.init_size);
-               pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size);
-               src = ucode->u.v2.data;
-               break;
-       case 0:
-       case 1:
-       case 2:
-               hdr_size = 24;
-               if (ucode_raw->size < hdr_size) {
-                       IWL_ERR(priv, "File size too small!\n");
-                       return -EINVAL;
-               }
-               pieces->build = 0;
-               pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size);
-               pieces->data_size = le32_to_cpu(ucode->u.v1.data_size);
-               pieces->init_size = le32_to_cpu(ucode->u.v1.init_size);
-               pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size);
-               src = ucode->u.v1.data;
-               break;
-       }
-
-       /* Verify size of file vs. image size info in file's header */
-       if (ucode_raw->size != hdr_size + pieces->inst_size +
-                               pieces->data_size + pieces->init_size +
-                               pieces->init_data_size) {
-
-               IWL_ERR(priv,
-                       "uCode file size %d does not match expected size\n",
-                       (int)ucode_raw->size);
-               return -EINVAL;
-       }
-
-       pieces->inst = src;
-       src += pieces->inst_size;
-       pieces->data = src;
-       src += pieces->data_size;
-       pieces->init = src;
-       src += pieces->init_size;
-       pieces->init_data = src;
-       src += pieces->init_data_size;
-
-       return 0;
-}
-
-static int iwlagn_load_firmware(struct iwl_priv *priv,
-                               const struct firmware *ucode_raw,
-                               struct iwlagn_firmware_pieces *pieces,
-                               struct iwlagn_ucode_capabilities *capa)
-{
-       struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data;
-       struct iwl_ucode_tlv *tlv;
-       size_t len = ucode_raw->size;
-       const u8 *data;
-       int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative;
-       int tmp;
-       u64 alternatives;
-       u32 tlv_len;
-       enum iwl_ucode_tlv_type tlv_type;
-       const u8 *tlv_data;
-
-       if (len < sizeof(*ucode)) {
-               IWL_ERR(priv, "uCode has invalid length: %zd\n", len);
-               return -EINVAL;
-       }
-
-       if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) {
-               IWL_ERR(priv, "invalid uCode magic: 0X%x\n",
-                       le32_to_cpu(ucode->magic));
-               return -EINVAL;
-       }
-
-       /*
-        * Check which alternatives are present, and "downgrade"
-        * when the chosen alternative is not present, warning
-        * the user when that happens. Some files may not have
-        * any alternatives, so don't warn in that case.
-        */
-       alternatives = le64_to_cpu(ucode->alternatives);
-       tmp = wanted_alternative;
-       if (wanted_alternative > 63)
-               wanted_alternative = 63;
-       while (wanted_alternative && !(alternatives & BIT(wanted_alternative)))
-               wanted_alternative--;
-       if (wanted_alternative && wanted_alternative != tmp)
-               IWL_WARN(priv,
-                        "uCode alternative %d not available, choosing %d\n",
-                        tmp, wanted_alternative);
-
-       priv->ucode_ver = le32_to_cpu(ucode->ver);
-       pieces->build = le32_to_cpu(ucode->build);
-       data = ucode->data;
-
-       len -= sizeof(*ucode);
-
-       while (len >= sizeof(*tlv)) {
-               u16 tlv_alt;
-
-               len -= sizeof(*tlv);
-               tlv = (void *)data;
-
-               tlv_len = le32_to_cpu(tlv->length);
-               tlv_type = le16_to_cpu(tlv->type);
-               tlv_alt = le16_to_cpu(tlv->alternative);
-               tlv_data = tlv->data;
-
-               if (len < tlv_len) {
-                       IWL_ERR(priv, "invalid TLV len: %zd/%u\n",
-                               len, tlv_len);
-                       return -EINVAL;
-               }
-               len -= ALIGN(tlv_len, 4);
-               data += sizeof(*tlv) + ALIGN(tlv_len, 4);
-
-               /*
-                * Alternative 0 is always valid.
-                *
-                * Skip alternative TLVs that are not selected.
-                */
-               if (tlv_alt != 0 && tlv_alt != wanted_alternative)
-                       continue;
-
-               switch (tlv_type) {
-               case IWL_UCODE_TLV_INST:
-                       pieces->inst = tlv_data;
-                       pieces->inst_size = tlv_len;
-                       break;
-               case IWL_UCODE_TLV_DATA:
-                       pieces->data = tlv_data;
-                       pieces->data_size = tlv_len;
-                       break;
-               case IWL_UCODE_TLV_INIT:
-                       pieces->init = tlv_data;
-                       pieces->init_size = tlv_len;
-                       break;
-               case IWL_UCODE_TLV_INIT_DATA:
-                       pieces->init_data = tlv_data;
-                       pieces->init_data_size = tlv_len;
-                       break;
-               case IWL_UCODE_TLV_BOOT:
-                       IWL_ERR(priv, "Found unexpected BOOT ucode\n");
-                       break;
-               case IWL_UCODE_TLV_PROBE_MAX_LEN:
-                       if (tlv_len != sizeof(u32))
-                               goto invalid_tlv_len;
-                       capa->max_probe_length =
-                                       le32_to_cpup((__le32 *)tlv_data);
-                       break;
-               case IWL_UCODE_TLV_PAN:
-                       if (tlv_len)
-                               goto invalid_tlv_len;
-                       capa->flags |= IWL_UCODE_TLV_FLAGS_PAN;
-                       break;
-               case IWL_UCODE_TLV_FLAGS:
-                       /* must be at least one u32 */
-                       if (tlv_len < sizeof(u32))
-                               goto invalid_tlv_len;
-                       /* and a proper number of u32s */
-                       if (tlv_len % sizeof(u32))
-                               goto invalid_tlv_len;
-                       /*
-                        * This driver only reads the first u32 as
-                        * right now no more features are defined,
-                        * if that changes then either the driver
-                        * will not work with the new firmware, or
-                        * it'll not take advantage of new features.
-                        */
-                       capa->flags = le32_to_cpup((__le32 *)tlv_data);
-                       break;
-               case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
-                       if (tlv_len != sizeof(u32))
-                               goto invalid_tlv_len;
-                       pieces->init_evtlog_ptr =
-                                       le32_to_cpup((__le32 *)tlv_data);
-                       break;
-               case IWL_UCODE_TLV_INIT_EVTLOG_SIZE:
-                       if (tlv_len != sizeof(u32))
-                               goto invalid_tlv_len;
-                       pieces->init_evtlog_size =
-                                       le32_to_cpup((__le32 *)tlv_data);
-                       break;
-               case IWL_UCODE_TLV_INIT_ERRLOG_PTR:
-                       if (tlv_len != sizeof(u32))
-                               goto invalid_tlv_len;
-                       pieces->init_errlog_ptr =
-                                       le32_to_cpup((__le32 *)tlv_data);
-                       break;
-               case IWL_UCODE_TLV_RUNT_EVTLOG_PTR:
-                       if (tlv_len != sizeof(u32))
-                               goto invalid_tlv_len;
-                       pieces->inst_evtlog_ptr =
-                                       le32_to_cpup((__le32 *)tlv_data);
-                       break;
-               case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE:
-                       if (tlv_len != sizeof(u32))
-                               goto invalid_tlv_len;
-                       pieces->inst_evtlog_size =
-                                       le32_to_cpup((__le32 *)tlv_data);
-                       break;
-               case IWL_UCODE_TLV_RUNT_ERRLOG_PTR:
-                       if (tlv_len != sizeof(u32))
-                               goto invalid_tlv_len;
-                       pieces->inst_errlog_ptr =
-                                       le32_to_cpup((__le32 *)tlv_data);
-                       break;
-               case IWL_UCODE_TLV_ENHANCE_SENS_TBL:
-                       if (tlv_len)
-                               goto invalid_tlv_len;
-                       priv->enhance_sensitivity_table = true;
-                       break;
-               case IWL_UCODE_TLV_WOWLAN_INST:
-                       pieces->wowlan_inst = tlv_data;
-                       pieces->wowlan_inst_size = tlv_len;
-                       break;
-               case IWL_UCODE_TLV_WOWLAN_DATA:
-                       pieces->wowlan_data = tlv_data;
-                       pieces->wowlan_data_size = tlv_len;
-                       break;
-               case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE:
-                       if (tlv_len != sizeof(u32))
-                               goto invalid_tlv_len;
-                       capa->standard_phy_calibration_size =
-                                       le32_to_cpup((__le32 *)tlv_data);
-                       break;
-               default:
-                       IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type);
-                       break;
-               }
-       }
-
-       if (len) {
-               IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len);
-               iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len);
-               return -EINVAL;
-       }
-
-       return 0;
-
- invalid_tlv_len:
-       IWL_ERR(priv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
-       iwl_print_hex_dump(priv, IWL_DL_FW, tlv_data, tlv_len);
-
-       return -EINVAL;
-}
-
-/**
- * iwl_ucode_callback - callback when firmware was loaded
- *
- * If loaded successfully, copies the firmware into buffers
- * for the card to fetch (via DMA).
- */
-static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
-{
-       struct iwl_priv *priv = context;
-       struct iwl_ucode_header *ucode;
-       int err;
-       struct iwlagn_firmware_pieces pieces;
-       const unsigned int api_max = cfg(priv)->ucode_api_max;
-       unsigned int api_ok = cfg(priv)->ucode_api_ok;
-       const unsigned int api_min = cfg(priv)->ucode_api_min;
-       u32 api_ver;
-       char buildstr[25];
-       u32 build;
-       struct iwlagn_ucode_capabilities ucode_capa = {
-               .max_probe_length = 200,
-               .standard_phy_calibration_size =
-                       IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE,
-       };
-
-       if (!api_ok)
-               api_ok = api_max;
-
-       memset(&pieces, 0, sizeof(pieces));
-
-       if (!ucode_raw) {
-               if (priv->fw_index <= api_ok)
-                       IWL_ERR(priv,
-                               "request for firmware file '%s' failed.\n",
-                               priv->firmware_name);
-               goto try_again;
-       }
-
-       IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n",
-                      priv->firmware_name, ucode_raw->size);
-
-       /* Make sure that we got at least the API version number */
-       if (ucode_raw->size < 4) {
-               IWL_ERR(priv, "File size way too small!\n");
-               goto try_again;
-       }
-
-       /* Data from ucode file:  header followed by uCode images */
-       ucode = (struct iwl_ucode_header *)ucode_raw->data;
-
-       if (ucode->ver)
-               err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces);
-       else
-               err = iwlagn_load_firmware(priv, ucode_raw, &pieces,
-                                          &ucode_capa);
-
-       if (err)
-               goto try_again;
-
-       api_ver = IWL_UCODE_API(priv->ucode_ver);
-       build = pieces.build;
-
-       /*
-        * 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 firmware header from here on forward
-        */
-       /* no api version check required for experimental uCode */
-       if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) {
-               if (api_ver < api_min || api_ver > api_max) {
-                       IWL_ERR(priv,
-                               "Driver unable to support your firmware API. "
-                               "Driver supports v%u, firmware is v%u.\n",
-                               api_max, api_ver);
-                       goto try_again;
-               }
-
-               if (api_ver < api_ok) {
-                       if (api_ok != api_max)
-                               IWL_ERR(priv, "Firmware has old API version, "
-                                       "expected v%u through v%u, got v%u.\n",
-                                       api_ok, api_max, api_ver);
-                       else
-                               IWL_ERR(priv, "Firmware has old API version, "
-                                       "expected v%u, got v%u.\n",
-                                       api_max, api_ver);
-                       IWL_ERR(priv, "New firmware can be obtained from "
-                                     "http://www.intellinuxwireless.org/.\n");
-               }
-       }
-
-       if (build)
-               sprintf(buildstr, " build %u%s", build,
-                      (priv->fw_index == UCODE_EXPERIMENTAL_INDEX)
-                               ? " (EXP)" : "");
-       else
-               buildstr[0] = '\0';
-
-       IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u%s\n",
-                IWL_UCODE_MAJOR(priv->ucode_ver),
-                IWL_UCODE_MINOR(priv->ucode_ver),
-                IWL_UCODE_API(priv->ucode_ver),
-                IWL_UCODE_SERIAL(priv->ucode_ver),
-                buildstr);
-
-       snprintf(priv->hw->wiphy->fw_version,
-                sizeof(priv->hw->wiphy->fw_version),
-                "%u.%u.%u.%u%s",
-                IWL_UCODE_MAJOR(priv->ucode_ver),
-                IWL_UCODE_MINOR(priv->ucode_ver),
-                IWL_UCODE_API(priv->ucode_ver),
-                IWL_UCODE_SERIAL(priv->ucode_ver),
-                buildstr);
-
-       /*
-        * For any of the failures below (before allocating pci memory)
-        * we will try to load a version with a smaller API -- maybe the
-        * user just got a corrupted version of the latest API.
-        */
-
-       IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
-                      priv->ucode_ver);
-       IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n",
-                      pieces.inst_size);
-       IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n",
-                      pieces.data_size);
-       IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n",
-                      pieces.init_size);
-       IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n",
-                      pieces.init_data_size);
-
-       /* Verify that uCode images will fit in card's SRAM */
-       if (pieces.inst_size > hw_params(priv).max_inst_size) {
-               IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n",
-                       pieces.inst_size);
-               goto try_again;
-       }
-
-       if (pieces.data_size > hw_params(priv).max_data_size) {
-               IWL_ERR(priv, "uCode data len %Zd too large to fit in\n",
-                       pieces.data_size);
-               goto try_again;
-       }
-
-       if (pieces.init_size > hw_params(priv).max_inst_size) {
-               IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n",
-                       pieces.init_size);
-               goto try_again;
-       }
-
-       if (pieces.init_data_size > hw_params(priv).max_data_size) {
-               IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n",
-                       pieces.init_data_size);
-               goto try_again;
-       }
-
-       /* Allocate ucode buffers for card's bus-master loading ... */
-
-       /* 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(bus(priv), &trans(priv)->ucode_rt.code,
-                             pieces.inst, pieces.inst_size))
-               goto err_pci_alloc;
-       if (iwl_alloc_fw_desc(bus(priv), &trans(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(bus(priv), &trans(priv)->ucode_init.code,
-                                     pieces.init, pieces.init_size))
-                       goto err_pci_alloc;
-               if (iwl_alloc_fw_desc(bus(priv), &trans(priv)->ucode_init.data,
-                                     pieces.init_data, pieces.init_data_size))
-                       goto err_pci_alloc;
-       }
-
-       /* WoWLAN instructions and data */
-       if (pieces.wowlan_inst_size && pieces.wowlan_data_size) {
-               if (iwl_alloc_fw_desc(bus(priv),
-                                     &trans(priv)->ucode_wowlan.code,
-                                     pieces.wowlan_inst,
-                                     pieces.wowlan_inst_size))
-                       goto err_pci_alloc;
-               if (iwl_alloc_fw_desc(bus(priv),
-                                     &trans(priv)->ucode_wowlan.data,
-                                     pieces.wowlan_data,
-                                     pieces.wowlan_data_size))
-                       goto err_pci_alloc;
-       }
-
-       /* Now that we can no longer fail, copy information */
-
-       /*
-        * The (size - 16) / 12 formula is based on the information recorded
-        * for each event, which is of mode 1 (including timestamp) for all
-        * new microcodes that include this information.
-        */
-       priv->init_evtlog_ptr = pieces.init_evtlog_ptr;
-       if (pieces.init_evtlog_size)
-               priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
-       else
-               priv->init_evtlog_size =
-                       cfg(priv)->base_params->max_event_log_size;
-       priv->init_errlog_ptr = pieces.init_errlog_ptr;
-       priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
-       if (pieces.inst_evtlog_size)
-               priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
-       else
-               priv->inst_evtlog_size =
-                       cfg(priv)->base_params->max_event_log_size;
-       priv->inst_errlog_ptr = pieces.inst_errlog_ptr;
-#ifndef CONFIG_IWLWIFI_P2P
-       ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
-#endif
-
-       priv->new_scan_threshold_behaviour =
-               !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
-
-       if (!(cfg(priv)->sku & EEPROM_SKU_CAP_IPAN_ENABLE))
-               ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
-
-       /*
-        * if not PAN, then don't support P2P -- might be a uCode
-        * packaging bug or due to the eeprom check above
-        */
-       if (!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN))
-               ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
-
-       if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
-               priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
-               priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
-       } else {
-               priv->sta_key_max_num = STA_KEY_MAX_NUM;
-               priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
-       }
-       /*
-        * figure out the offset of chain noise reset and gain commands
-        * base on the size of standard phy calibration commands table size
-        */
-       if (ucode_capa.standard_phy_calibration_size >
-           IWL_MAX_PHY_CALIBRATE_TBL_SIZE)
-               ucode_capa.standard_phy_calibration_size =
-                       IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE;
-
-       priv->phy_calib_chain_noise_reset_cmd =
-               ucode_capa.standard_phy_calibration_size;
-       priv->phy_calib_chain_noise_gain_cmd =
-               ucode_capa.standard_phy_calibration_size + 1;
-
-       /* initialize all valid contexts */
-       iwl_init_context(priv, ucode_capa.flags);
-
-       /**************************************************
-        * This is still part of probe() in a sense...
-        *
-        * 9. Setup and register with mac80211 and debugfs
-        **************************************************/
-       err = iwlagn_mac_setup_register(priv, &ucode_capa);
-       if (err)
-               goto out_unbind;
-
-       err = iwl_dbgfs_register(priv, DRV_NAME);
-       if (err)
-               IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
-
-       /* We have our copies now, allow OS release its copies */
-       release_firmware(ucode_raw);
-       complete(&priv->firmware_loading_complete);
-       return;
-
- try_again:
-       /* try next, if any */
-       if (iwl_request_firmware(priv, false))
-               goto out_unbind;
-       release_firmware(ucode_raw);
-       return;
-
- err_pci_alloc:
-       IWL_ERR(priv, "failed to allocate pci memory\n");
-       iwl_dealloc_ucode(trans(priv));
- out_unbind:
-       complete(&priv->firmware_loading_complete);
-       device_release_driver(bus(priv)->dev);
-       release_firmware(ucode_raw);
-}
-
 static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
 {
        struct iwl_ct_kill_config cmd;
        struct iwl_ct_kill_throttling_config adv_cmd;
-       unsigned long flags;
        int ret = 0;
 
-       spin_lock_irqsave(&priv->shrd->lock, flags);
-       iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR,
+       iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR,
                    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-       spin_unlock_irqrestore(&priv->shrd->lock, flags);
+
        priv->thermal_throttle.ct_kill_toggle = false;
 
        if (cfg(priv)->base_params->support_ct_kill_exit) {
@@ -1169,7 +563,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
                adv_cmd.critical_temperature_exit =
                        cpu_to_le32(hw_params(priv).ct_kill_exit_threshold);
 
-               ret = iwl_trans_send_cmd_pdu(trans(priv),
+               ret = iwl_dvm_send_cmd_pdu(priv,
                                       REPLY_CT_KILL_CONFIG_CMD,
                                       CMD_SYNC, sizeof(adv_cmd), &adv_cmd);
                if (ret)
@@ -1184,7 +578,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
                cmd.critical_temperature_R =
                        cpu_to_le32(hw_params(priv).ct_kill_threshold);
 
-               ret = iwl_trans_send_cmd_pdu(trans(priv),
+               ret = iwl_dvm_send_cmd_pdu(priv,
                                       REPLY_CT_KILL_CONFIG_CMD,
                                       CMD_SYNC, sizeof(cmd), &cmd);
                if (ret)
@@ -1210,7 +604,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
        calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_RT_CFG_ALL;
        calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
 
-       return iwl_trans_send_cmd(trans(priv), &cmd);
+       return iwl_dvm_send_cmd(priv, &cmd);
 }
 
 
@@ -1220,9 +614,9 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
          .valid = cpu_to_le32(valid_tx_ant),
        };
 
-       if (IWL_UCODE_API(priv->ucode_ver) > 1) {
+       if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) {
                IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
-               return iwl_trans_send_cmd_pdu(trans(priv),
+               return iwl_dvm_send_cmd_pdu(priv,
                                        TX_ANT_CONFIGURATION_CMD,
                                        CMD_SYNC,
                                        sizeof(struct iwl_tx_ant_config_cmd),
@@ -1243,9 +637,6 @@ int iwl_alive_start(struct iwl_priv *priv)
        int ret = 0;
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
-       /*TODO: this should go to the transport layer */
-       iwl_reset_ict(trans(priv));
-
        IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
 
        /* After the ALIVE response, we can send host commands to the uCode */
@@ -1278,14 +669,14 @@ int iwl_alive_start(struct iwl_priv *priv)
                priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
                priv->cur_rssi_ctx = NULL;
 
-               iwl_send_prio_tbl(trans(priv));
+               iwl_send_prio_tbl(priv);
 
                /* FIXME: w/a to force change uCode BT state machine */
-               ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN,
+               ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
                                         BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
                if (ret)
                        return ret;
-               ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_CLOSE,
+               ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
                                         BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
                if (ret)
                        return ret;
@@ -1306,9 +697,9 @@ int iwl_alive_start(struct iwl_priv *priv)
        priv->active_rate = IWL_RATES_MASK;
 
        /* Configure Tx antenna selection based on H/W config */
-       iwlagn_send_tx_ant_config(priv, cfg(priv)->valid_tx_ant);
+       iwlagn_send_tx_ant_config(priv, hw_params(priv).valid_tx_ant);
 
-       if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) {
+       if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
                struct iwl_rxon_cmd *active_rxon =
                                (struct iwl_rxon_cmd *)&ctx->active;
                /* apply any changes in staging */
@@ -1323,7 +714,7 @@ int iwl_alive_start(struct iwl_priv *priv)
                iwlagn_set_rxon_chain(priv, ctx);
        }
 
-       if (!priv->shrd->wowlan) {
+       if (!priv->wowlan) {
                /* WoWLAN ucode will not reply in the same way, skip it */
                iwl_reset_run_time_calib(priv);
        }
@@ -1343,14 +734,48 @@ int iwl_alive_start(struct iwl_priv *priv)
        return iwl_power_update_mode(priv, true);
 }
 
-static void iwl_cancel_deferred_work(struct iwl_priv *priv);
+/**
+ * iwl_clear_driver_stations - clear knowledge of all stations from driver
+ * @priv: iwl priv struct
+ *
+ * This is called during iwl_down() to make sure that in the case
+ * we're coming there from a hardware restart mac80211 will be
+ * able to reconfigure stations -- if we're getting there in the
+ * normal down flow then the stations will already be cleared.
+ */
+static void iwl_clear_driver_stations(struct iwl_priv *priv)
+{
+       struct iwl_rxon_context *ctx;
+
+       spin_lock_bh(&priv->sta_lock);
+       memset(priv->stations, 0, sizeof(priv->stations));
+       priv->num_stations = 0;
+
+       priv->ucode_key_table = 0;
+
+       for_each_context(priv, ctx) {
+               /*
+                * Remove all key information that is not stored as part
+                * of station information since mac80211 may not have had
+                * a chance to remove all the keys. When device is
+                * reconfigured by mac80211 after an error all keys will
+                * be reconfigured.
+                */
+               memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
+               ctx->key_mapping_keys = 0;
+       }
+
+       spin_unlock_bh(&priv->sta_lock);
+}
 
-void __iwl_down(struct iwl_priv *priv)
+void iwl_down(struct iwl_priv *priv)
 {
        int exit_pending;
 
        IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
 
+       lockdep_assert_held(&priv->mutex);
+
        iwl_scan_cancel_timeout(priv, 200);
 
        /*
@@ -1408,15 +833,6 @@ void __iwl_down(struct iwl_priv *priv)
        priv->beacon_skb = NULL;
 }
 
-void iwl_down(struct iwl_priv *priv)
-{
-       mutex_lock(&priv->shrd->mutex);
-       __iwl_down(priv);
-       mutex_unlock(&priv->shrd->mutex);
-
-       iwl_cancel_deferred_work(priv);
-}
-
 /*****************************************************************************
  *
  * Workqueue callbacks
@@ -1428,11 +844,11 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
        struct iwl_priv *priv = container_of(work, struct iwl_priv,
                        run_time_calib_work);
 
-       mutex_lock(&priv->shrd->mutex);
+       mutex_lock(&priv->mutex);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) ||
            test_bit(STATUS_SCANNING, &priv->shrd->status)) {
-               mutex_unlock(&priv->shrd->mutex);
+               mutex_unlock(&priv->mutex);
                return;
        }
 
@@ -1441,7 +857,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
                iwl_sensitivity_calibration(priv);
        }
 
-       mutex_unlock(&priv->shrd->mutex);
+       mutex_unlock(&priv->mutex);
 }
 
 void iwlagn_prepare_restart(struct iwl_priv *priv)
@@ -1453,7 +869,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv)
        u8 bt_status;
        bool bt_is_sco;
 
-       lockdep_assert_held(&priv->shrd->mutex);
+       lockdep_assert_held(&priv->mutex);
 
        for_each_context(priv, ctx)
                ctx->vif = NULL;
@@ -1474,7 +890,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv)
        bt_status = priv->bt_status;
        bt_is_sco = priv->bt_is_sco;
 
-       __iwl_down(priv);
+       iwl_down(priv);
 
        priv->bt_full_concurrent = bt_full_concurrent;
        priv->bt_ci_compliance = bt_ci_compliance;
@@ -1491,9 +907,9 @@ static void iwl_bg_restart(struct work_struct *data)
                return;
 
        if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) {
-               mutex_lock(&priv->shrd->mutex);
+               mutex_lock(&priv->mutex);
                iwlagn_prepare_restart(priv);
-               mutex_unlock(&priv->shrd->mutex);
+               mutex_unlock(&priv->mutex);
                iwl_cancel_deferred_work(priv);
                ieee80211_restart_hw(priv->hw);
        } else {
@@ -1508,7 +924,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv)
 {
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
 
-       lockdep_assert_held(&priv->shrd->mutex);
+       lockdep_assert_held(&priv->mutex);
 
        if (!priv->hw_roc_setup)
                return;
@@ -1531,9 +947,9 @@ static void iwlagn_disable_roc_work(struct work_struct *work)
        struct iwl_priv *priv = container_of(work, struct iwl_priv,
                                             hw_roc_disable_work.work);
 
-       mutex_lock(&priv->shrd->mutex);
+       mutex_lock(&priv->mutex);
        iwlagn_disable_roc(priv);
-       mutex_unlock(&priv->shrd->mutex);
+       mutex_unlock(&priv->mutex);
 }
 
 /*****************************************************************************
@@ -1544,7 +960,7 @@ static void iwlagn_disable_roc_work(struct work_struct *work)
 
 static void iwl_setup_deferred_work(struct iwl_priv *priv)
 {
-       priv->shrd->workqueue = create_singlethread_workqueue(DRV_NAME);
+       priv->workqueue = create_singlethread_workqueue(DRV_NAME);
 
        init_waitqueue_head(&priv->shrd->wait_command_queue);
 
@@ -1559,8 +975,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 
        iwl_setup_scan_deferred_work(priv);
 
-       if (cfg(priv)->lib->bt_setup_deferred_work)
-               cfg(priv)->lib->bt_setup_deferred_work(priv);
+       if (cfg(priv)->bt_params)
+               iwlagn_bt_setup_deferred_work(priv);
 
        init_timer(&priv->statistics_periodic);
        priv->statistics_periodic.data = (unsigned long)priv;
@@ -1575,10 +991,10 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
        priv->watchdog.function = iwl_bg_watchdog;
 }
 
-static void iwl_cancel_deferred_work(struct iwl_priv *priv)
+void iwl_cancel_deferred_work(struct iwl_priv *priv)
 {
-       if (cfg(priv)->lib->cancel_deferred_work)
-               cfg(priv)->lib->cancel_deferred_work(priv);
+       if (cfg(priv)->bt_params)
+               iwlagn_bt_cancel_deferred_work(priv);
 
        cancel_work_sync(&priv->run_time_calib_work);
        cancel_work_sync(&priv->beacon_update);
@@ -1593,8 +1009,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
        del_timer_sync(&priv->ucode_trace);
 }
 
-static void iwl_init_hw_rates(struct iwl_priv *priv,
-                             struct ieee80211_rate *rates)
+static void iwl_init_hw_rates(struct ieee80211_rate *rates)
 {
        int i;
 
@@ -1618,21 +1033,26 @@ static int iwl_init_drv(struct iwl_priv *priv)
 {
        int ret;
 
-       spin_lock_init(&priv->shrd->sta_lock);
+       spin_lock_init(&priv->sta_lock);
 
-       mutex_init(&priv->shrd->mutex);
+       mutex_init(&priv->mutex);
 
-       INIT_LIST_HEAD(&trans(priv)->calib_results);
+       INIT_LIST_HEAD(&priv->calib_results);
 
        priv->ieee_channels = NULL;
        priv->ieee_rates = NULL;
        priv->band = IEEE80211_BAND_2GHZ;
 
+       priv->plcp_delta_threshold =
+               cfg(priv)->base_params->plcp_delta_threshold;
+
        priv->iw_mode = NL80211_IFTYPE_STATION;
        priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
        priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
        priv->agg_tids_count = 0;
 
+       priv->ucode_owner = IWL_OWNERSHIP_DRIVER;
+
        /* initialize force reset */
        priv->force_reset[IWL_RF_RESET].reset_duration =
                IWL_DELAY_NEXT_FORCE_RF_RESET;
@@ -1668,7 +1088,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
                IWL_ERR(priv, "initializing geos failed: %d\n", ret);
                goto err_free_channel_map;
        }
-       iwl_init_hw_rates(priv, priv->ieee_rates);
+       iwl_init_hw_rates(priv->ieee_rates);
 
        return 0;
 
@@ -1682,29 +1102,25 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
 {
        iwl_free_geos(priv);
        iwl_free_channel_map(priv);
-       if (priv->tx_cmd_pool)
-               kmem_cache_destroy(priv->tx_cmd_pool);
        kfree(priv->scan_cmd);
        kfree(priv->beacon_cmd);
        kfree(rcu_dereference_raw(priv->noa_data));
+       iwl_calib_free_results(priv);
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        kfree(priv->wowlan_sram);
 #endif
 }
 
-
-
-static u32 iwl_hw_detect(struct iwl_priv *priv)
-{
-       return iwl_read32(bus(priv), CSR_HW_REV);
-}
-
 /* Size of one Rx buffer in host DRAM */
 #define IWL_RX_BUF_SIZE_4K (4 * 1024)
 #define IWL_RX_BUF_SIZE_8K (8 * 1024)
 
-static int iwl_set_hw_params(struct iwl_priv *priv)
+static void iwl_set_hw_params(struct iwl_priv *priv)
 {
+       if (cfg(priv)->ht_params)
+               hw_params(priv).use_rts_for_aggregation =
+                       cfg(priv)->ht_params->use_rts_for_aggregation;
+
        if (iwlagn_mod_params.amsdu_size_8K)
                hw_params(priv).rx_page_order =
                        get_order(IWL_RX_BUF_SIZE_8K);
@@ -1713,49 +1129,46 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
                        get_order(IWL_RX_BUF_SIZE_4K);
 
        if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
-               cfg(priv)->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
+               hw_params(priv).sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
 
        hw_params(priv).num_ampdu_queues =
                cfg(priv)->base_params->num_of_ampdu_queues;
-       hw_params(priv).shadow_reg_enable =
-               cfg(priv)->base_params->shadow_reg_enable;
-       hw_params(priv).sku = cfg(priv)->sku;
        hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout;
 
        /* Device-specific setup */
-       return cfg(priv)->lib->set_hw_params(priv);
+       cfg(priv)->lib->set_hw_params(priv);
 }
 
 
 
 static void iwl_debug_config(struct iwl_priv *priv)
 {
-       dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEBUG "
+       dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEBUG "
 #ifdef CONFIG_IWLWIFI_DEBUG
                "enabled\n");
 #else
                "disabled\n");
 #endif
-       dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEBUGFS "
+       dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEBUGFS "
 #ifdef CONFIG_IWLWIFI_DEBUGFS
                "enabled\n");
 #else
                "disabled\n");
 #endif
-       dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TRACING "
+       dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TRACING "
 #ifdef CONFIG_IWLWIFI_DEVICE_TRACING
                "enabled\n");
 #else
                "disabled\n");
 #endif
 
-       dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TESTMODE "
+       dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TESTMODE "
 #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
                "enabled\n");
 #else
                "disabled\n");
 #endif
-       dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_P2P "
+       dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_P2P "
 #ifdef CONFIG_IWLWIFI_P2P
                "enabled\n");
 #else
@@ -1763,46 +1176,45 @@ static void iwl_debug_config(struct iwl_priv *priv)
 #endif
 }
 
-int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
-               struct iwl_cfg *cfg)
+static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
+                                                const struct iwl_fw *fw)
 {
        int err = 0;
        struct iwl_priv *priv;
        struct ieee80211_hw *hw;
+       struct iwl_op_mode *op_mode;
        u16 num_mac;
-       u32 hw_rev;
+       u32 ucode_flags;
 
        /************************
         * 1. Allocating HW data
         ************************/
        hw = iwl_alloc_all();
        if (!hw) {
-               pr_err("%s: Cannot allocate network device\n", cfg->name);
+               pr_err("%s: Cannot allocate network device\n",
+                               cfg(trans)->name);
                err = -ENOMEM;
                goto out;
        }
 
-       priv = hw->priv;
-       priv->shrd = &priv->_shrd;
-       bus->shrd = priv->shrd;
-       priv->shrd->bus = bus;
-       priv->shrd->priv = priv;
+       op_mode = hw->priv;
+       op_mode->ops = &iwl_dvm_ops;
+       priv = IWL_OP_MODE_GET_DVM(op_mode);
+       priv->shrd = trans->shrd;
+       priv->fw = fw;
+       /* TODO: remove fw from shared data later */
+       priv->shrd->fw = fw;
 
-       priv->shrd->trans = trans_ops->alloc(priv->shrd);
-       if (priv->shrd->trans == NULL) {
-               err = -ENOMEM;
-               goto out_free_traffic_mem;
-       }
+       iwl_trans_configure(trans(priv), op_mode);
 
        /* At this point both hw and priv are allocated. */
 
-       SET_IEEE80211_DEV(hw, bus(priv)->dev);
+       SET_IEEE80211_DEV(priv->hw, trans(priv)->dev);
 
-       /* what debugging capabilities we have */
+       /* show what debugging capabilities we have */
        iwl_debug_config(priv);
 
        IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
-       cfg(priv) = cfg;
 
        /* is antenna coupling more than 35dB ? */
        priv->bt_ant_couple_ok =
@@ -1821,47 +1233,35 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
        /* these spin locks will be used in apm_ops.init and EEPROM access
         * we should init now
         */
-       spin_lock_init(&bus(priv)->reg_lock);
-       spin_lock_init(&priv->shrd->lock);
-
-       /*
-        * stop and reset the on-board processor just in case it is in a
-        * strange state ... like being left stranded by a primary kernel
-        * and this is now the kdump kernel trying to start up
-        */
-       iwl_write32(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+       spin_lock_init(&trans(priv)->reg_lock);
+       spin_lock_init(&priv->statistics.lock);
 
        /***********************
         * 3. Read REV register
         ***********************/
-       hw_rev = iwl_hw_detect(priv);
        IWL_INFO(priv, "Detected %s, REV=0x%X\n",
-               cfg(priv)->name, hw_rev);
+               cfg(priv)->name, trans(priv)->hw_rev);
 
-       err = iwl_trans_request_irq(trans(priv));
+       err = iwl_trans_start_hw(trans(priv));
        if (err)
-               goto out_free_trans;
-
-       if (iwl_trans_prepare_card_hw(trans(priv))) {
-               err = -EIO;
-               IWL_WARN(priv, "Failed, HW not ready\n");
-               goto out_free_trans;
-       }
+               goto out_free_traffic_mem;
 
        /*****************
         * 4. Read EEPROM
         *****************/
        /* Read the EEPROM */
-       err = iwl_eeprom_init(priv, hw_rev);
+       err = iwl_eeprom_init(trans(priv), trans(priv)->hw_rev);
+       /* Reset chip to save power until we load uCode during "up". */
+       iwl_trans_stop_hw(trans(priv));
        if (err) {
                IWL_ERR(priv, "Unable to init EEPROM\n");
-               goto out_free_trans;
+               goto out_free_traffic_mem;
        }
        err = iwl_eeprom_check_version(priv);
        if (err)
                goto out_free_eeprom;
 
-       err = iwl_eeprom_check_sku(priv);
+       err = iwl_eeprom_init_hw_params(priv);
        if (err)
                goto out_free_eeprom;
 
@@ -1881,11 +1281,23 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
        /************************
         * 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;
-       }
+       iwl_set_hw_params(priv);
+
+       ucode_flags = fw->ucode_capa.flags;
+
+#ifndef CONFIG_IWLWIFI_P2P
+       ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+#endif
+       if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE))
+               ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+
+       /*
+        * if not PAN, then don't support P2P -- might be a uCode
+        * packaging bug or due to the eeprom check above
+        */
+       if (!(ucode_flags & IWL_UCODE_TLV_FLAGS_PAN))
+               ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
+
 
        /*******************
         * 6. Setup priv
@@ -1903,62 +1315,71 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
        iwl_setup_rx_handlers(priv);
        iwl_testmode_init(priv);
 
-       /*********************************************
-        * 8. Enable interrupts
-        *********************************************/
+       iwl_power_initialize(priv);
+       iwl_tt_initialize(priv);
 
-       iwl_enable_rfkill_int(priv);
+       snprintf(priv->hw->wiphy->fw_version,
+                sizeof(priv->hw->wiphy->fw_version),
+                "%s", fw->fw_version);
 
-       /* If platform's RF_KILL switch is NOT set to KILL */
-       if (iwl_read32(bus(priv),
-                       CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
-               clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
-       else
-               set_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
+       priv->new_scan_threshold_behaviour =
+               !!(ucode_flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
 
-       wiphy_rfkill_set_hw_state(priv->hw->wiphy,
-               test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
+       if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
+               priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
+               priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
+       } else {
+               priv->sta_key_max_num = STA_KEY_MAX_NUM;
+               priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+       }
 
-       iwl_power_initialize(priv);
-       iwl_tt_initialize(priv);
+       priv->phy_calib_chain_noise_reset_cmd =
+               fw->ucode_capa.standard_phy_calibration_size;
+       priv->phy_calib_chain_noise_gain_cmd =
+               fw->ucode_capa.standard_phy_calibration_size + 1;
 
-       init_completion(&priv->firmware_loading_complete);
+       /* initialize all valid contexts */
+       iwl_init_context(priv, ucode_flags);
 
-       err = iwl_request_firmware(priv, true);
+       /**************************************************
+        * This is still part of probe() in a sense...
+        *
+        * 9. Setup and register with mac80211 and debugfs
+        **************************************************/
+       err = iwlagn_mac_setup_register(priv, &fw->ucode_capa);
        if (err)
                goto out_destroy_workqueue;
 
-       return 0;
+       err = iwl_dbgfs_register(priv, DRV_NAME);
+       if (err)
+               IWL_ERR(priv,
+                       "failed to create debugfs files. Ignoring error: %d\n",
+                       err);
+
+       return op_mode;
 
 out_destroy_workqueue:
-       destroy_workqueue(priv->shrd->workqueue);
-       priv->shrd->workqueue = NULL;
+       destroy_workqueue(priv->workqueue);
+       priv->workqueue = NULL;
        iwl_uninit_drv(priv);
 out_free_eeprom:
        iwl_eeprom_free(priv->shrd);
-out_free_trans:
-       iwl_trans_free(trans(priv));
 out_free_traffic_mem:
        iwl_free_traffic_mem(priv);
        ieee80211_free_hw(priv->hw);
 out:
-       return err;
+       op_mode = NULL;
+       return op_mode;
 }
 
-void __devexit iwl_remove(struct iwl_priv * priv)
+static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
 {
-       wait_for_completion(&priv->firmware_loading_complete);
+       struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
 
        IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
        iwl_dbgfs_unregister(priv);
 
-       /* ieee80211_unregister_hw call wil cause iwlagn_mac_stop to
-        * to be called and iwl_down since we are removing the device
-        * we need to set STATUS_EXIT_PENDING bit.
-        */
-       set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
-
        iwl_testmode_cleanup(priv);
        iwlagn_mac_unregister(priv);
 
@@ -1967,22 +1388,18 @@ void __devexit iwl_remove(struct iwl_priv * priv)
        /*This will stop the queues, move the device to low power state */
        iwl_trans_stop_device(trans(priv));
 
-       iwl_dealloc_ucode(trans(priv));
-
        iwl_eeprom_free(priv->shrd);
 
        /*netif_stop_queue(dev); */
-       flush_workqueue(priv->shrd->workqueue);
+       flush_workqueue(priv->workqueue);
 
        /* ieee80211_unregister_hw calls iwlagn_mac_stop, which flushes
-        * priv->shrd->workqueue... so we can't take down the workqueue
+        * priv->workqueue... so we can't take down the workqueue
         * until now... */
-       destroy_workqueue(priv->shrd->workqueue);
-       priv->shrd->workqueue = NULL;
+       destroy_workqueue(priv->workqueue);
+       priv->workqueue = NULL;
        iwl_free_traffic_mem(priv);
 
-       iwl_trans_free(trans(priv));
-
        iwl_uninit_drv(priv);
 
        dev_kfree_skb(priv->beacon_skb);
@@ -1990,12 +1407,77 @@ void __devexit iwl_remove(struct iwl_priv * priv)
        ieee80211_free_hw(priv->hw);
 }
 
+static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
+{
+       struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+       if (!iwl_check_for_ct_kill(priv)) {
+               IWL_ERR(priv, "Restarting adapter queue is full\n");
+               iwl_nic_error(op_mode);
+       }
+}
+
+static void iwl_nic_config(struct iwl_op_mode *op_mode)
+{
+       struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+       cfg(priv)->lib->nic_config(priv);
+}
+
+static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
+{
+       struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+       set_bit(ac, &priv->transport_queue_stop);
+       ieee80211_stop_queue(priv->hw, ac);
+}
+
+static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
+{
+       struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+       clear_bit(ac, &priv->transport_queue_stop);
+
+       if (!priv->passive_no_rx)
+               ieee80211_wake_queue(priv->hw, ac);
+}
+
+void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
+{
+       int ac;
+
+       if (!priv->passive_no_rx)
+               return;
+
+       for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) {
+               if (!test_bit(ac, &priv->transport_queue_stop))
+                       ieee80211_wake_queue(priv->hw, ac);
+       }
+
+       priv->passive_no_rx = false;
+}
+
+const struct iwl_op_mode_ops iwl_dvm_ops = {
+       .start = iwl_op_mode_dvm_start,
+       .stop = iwl_op_mode_dvm_stop,
+       .rx = iwl_rx_dispatch,
+       .queue_full = iwl_stop_sw_queue,
+       .queue_not_full = iwl_wake_sw_queue,
+       .hw_rf_kill = iwl_set_hw_rfkill_state,
+       .free_skb = iwl_free_skb,
+       .nic_error = iwl_nic_error,
+       .cmd_queue_full = iwl_cmd_queue_full,
+       .nic_config = iwl_nic_config,
+};
 
 /*****************************************************************************
  *
  * driver and module entry point
  *
  *****************************************************************************/
+
+struct kmem_cache *iwl_tx_cmd_pool;
+
 static int __init iwl_init(void)
 {
 
@@ -2003,20 +1485,27 @@ static int __init iwl_init(void)
        pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
        pr_info(DRV_COPYRIGHT "\n");
 
+       iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd",
+                                           sizeof(struct iwl_device_cmd),
+                                           sizeof(void *), 0, NULL);
+       if (!iwl_tx_cmd_pool)
+               return -ENOMEM;
+
        ret = iwlagn_rate_control_register();
        if (ret) {
                pr_err("Unable to register rate control algorithm: %d\n", ret);
-               return ret;
+               goto error_rc_register;
        }
 
        ret = iwl_pci_register_driver();
-
        if (ret)
-               goto error_register;
+               goto error_pci_register;
        return ret;
 
-error_register:
+error_pci_register:
        iwlagn_rate_control_unregister();
+error_rc_register:
+       kmem_cache_destroy(iwl_tx_cmd_pool);
        return ret;
 }
 
@@ -2024,6 +1513,7 @@ static void __exit iwl_exit(void)
 {
        iwl_pci_unregister_driver();
        iwlagn_rate_control_unregister();
+       kmem_cache_destroy(iwl_tx_cmd_pool);
 }
 
 module_exit(iwl_exit);
@@ -2037,8 +1527,6 @@ MODULE_PARM_DESC(debug, "debug output mask");
 
 module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO);
 MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
-module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO);
-MODULE_PARM_DESC(queues_num, "number of hw queues.");
 module_param_named(11n_disable, iwlagn_mod_params.disable_11n, uint, S_IRUGO);
 MODULE_PARM_DESC(11n_disable,
        "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");
@@ -2097,7 +1585,7 @@ 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)");
+               "1=On(RF On)/Off(RF Off), 2=blinking, 3=Off (default: 0)");
 
 module_param_named(power_save, iwlagn_mod_params.power_save,
                bool, S_IRUGO);