]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/net/wireless/iwlwifi/iwl-agn.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial
[linux-2.6.git] / drivers / net / wireless / iwlwifi / iwl-agn.c
index 9a6f7a03be88af520efd40843889ccc33ea18012..08e3cae4fa5a1a128fd15af1d8bddbe15b1338fe 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
@@ -85,7 +85,6 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
 MODULE_VERSION(DRV_VERSION);
 MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("iwl4965");
 
 static int iwlagn_ant_coupling;
 static bool iwlagn_bt_ch_announce = 1;
@@ -103,70 +102,6 @@ void iwl_update_chain_flags(struct iwl_priv *priv)
        }
 }
 
-static void iwl_clear_free_frames(struct iwl_priv *priv)
-{
-       struct list_head *element;
-
-       IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n",
-                      priv->frames_count);
-
-       while (!list_empty(&priv->free_frames)) {
-               element = priv->free_frames.next;
-               list_del(element);
-               kfree(list_entry(element, struct iwl_frame, list));
-               priv->frames_count--;
-       }
-
-       if (priv->frames_count) {
-               IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
-                           priv->frames_count);
-               priv->frames_count = 0;
-       }
-}
-
-static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
-{
-       struct iwl_frame *frame;
-       struct list_head *element;
-       if (list_empty(&priv->free_frames)) {
-               frame = kzalloc(sizeof(*frame), GFP_KERNEL);
-               if (!frame) {
-                       IWL_ERR(priv, "Could not allocate frame!\n");
-                       return NULL;
-               }
-
-               priv->frames_count++;
-               return frame;
-       }
-
-       element = priv->free_frames.next;
-       list_del(element);
-       return list_entry(element, struct iwl_frame, list);
-}
-
-static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
-{
-       memset(frame, 0, sizeof(*frame));
-       list_add(&frame->list, &priv->free_frames);
-}
-
-static u32 iwl_fill_beacon_frame(struct iwl_priv *priv,
-                                struct ieee80211_hdr *hdr,
-                                int left)
-{
-       lockdep_assert_held(&priv->mutex);
-
-       if (!priv->beacon_skb)
-               return 0;
-
-       if (priv->beacon_skb->len > left)
-               return 0;
-
-       memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
-
-       return priv->beacon_skb->len;
-}
-
 /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
 static void iwl_set_beacon_tim(struct iwl_priv *priv,
                               struct iwl_tx_beacon_cmd *tx_beacon_cmd,
@@ -194,13 +129,18 @@ static void iwl_set_beacon_tim(struct iwl_priv *priv,
                IWL_WARN(priv, "Unable to find TIM Element in beacon\n");
 }
 
-static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
-                                      struct iwl_frame *frame)
+int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
 {
        struct iwl_tx_beacon_cmd *tx_beacon_cmd;
+       struct iwl_host_cmd cmd = {
+               .id = REPLY_TX_BEACON,
+               .flags = CMD_SIZE_HUGE,
+       };
        u32 frame_size;
        u32 rate_flags;
        u32 rate;
+       int err;
+
        /*
         * We have to set up the TX command, the TX Beacon command, and the
         * beacon contents.
@@ -213,17 +153,19 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
                return 0;
        }
 
-       /* Initialize memory */
-       tx_beacon_cmd = &frame->u.beacon;
-       memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
+       if (WARN_ON(!priv->beacon_skb))
+               return -EINVAL;
+
+       /* Allocate beacon memory */
+       tx_beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd) + priv->beacon_skb->len,
+                               GFP_KERNEL);
+       if (!tx_beacon_cmd)
+               return -ENOMEM;
+
+       frame_size = priv->beacon_skb->len;
 
        /* Set up TX beacon contents */
-       frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame,
-                               sizeof(frame->u) - sizeof(*tx_beacon_cmd));
-       if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
-               return 0;
-       if (!frame_size)
-               return 0;
+       memcpy(tx_beacon_cmd->frame, priv->beacon_skb->data, frame_size);
 
        /* Set up TX command fields */
        tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
@@ -246,35 +188,16 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
        tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate,
                        rate_flags);
 
-       return sizeof(*tx_beacon_cmd) + frame_size;
-}
-
-int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
-{
-       struct iwl_frame *frame;
-       unsigned int frame_size;
-       int rc;
-
-       frame = iwl_get_free_frame(priv);
-       if (!frame) {
-               IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
-                         "command.\n");
-               return -ENOMEM;
-       }
-
-       frame_size = iwl_hw_get_beacon_cmd(priv, frame);
-       if (!frame_size) {
-               IWL_ERR(priv, "Error configuring the beacon command\n");
-               iwl_free_frame(priv, frame);
-               return -EINVAL;
-       }
+       /* Submit command */
+       cmd.len = sizeof(*tx_beacon_cmd) + frame_size;
+       cmd.data = tx_beacon_cmd;
 
-       rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
-                             &frame->u.cmd[0]);
+       err = iwl_send_cmd_sync(priv, &cmd);
 
-       iwl_free_frame(priv, frame);
+       /* Free temporary storage */
+       kfree(tx_beacon_cmd);
 
-       return rc;
+       return err;
 }
 
 static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
@@ -395,7 +318,9 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
                return -EINVAL;
        }
 
-       BUG_ON(addr & ~DMA_BIT_MASK(36));
+       if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
+               return -EINVAL;
+
        if (unlikely(addr & ~IWL_TX_DMA_MASK))
                IWL_ERR(priv, "Unaligned address = %llx\n",
                          (unsigned long long)addr);
@@ -409,7 +334,7 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
  * Tell nic where to find circular buffer of Tx Frame Descriptors for
  * given Tx queue, and enable the DMA channel used for that queue.
  *
- * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
+ * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
  * channels supported in hardware.
  */
 int iwl_hw_tx_queue_init(struct iwl_priv *priv,
@@ -424,47 +349,6 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv,
        return 0;
 }
 
-/******************************************************************************
- *
- * Generic RX handler implementations
- *
- ******************************************************************************/
-static void iwl_rx_reply_alive(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_alive_resp *palive;
-       struct delayed_work *pwork;
-
-       palive = &pkt->u.alive_frame;
-
-       IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
-                      "0x%01X 0x%01X\n",
-                      palive->is_valid, palive->ver_type,
-                      palive->ver_subtype);
-
-       if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
-               IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
-               memcpy(&priv->card_alive_init,
-                      &pkt->u.alive_frame,
-                      sizeof(struct iwl_init_alive_resp));
-               pwork = &priv->init_alive_start;
-       } else {
-               IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
-               memcpy(&priv->card_alive, &pkt->u.alive_frame,
-                      sizeof(struct iwl_alive_resp));
-               pwork = &priv->alive_start;
-       }
-
-       /* We delay the ALIVE response by 5ms to
-        * give the HW RF Kill time to activate... */
-       if (palive->is_valid == UCODE_VALID_OK)
-               queue_delayed_work(priv->workqueue, pwork,
-                                  msecs_to_jiffies(5));
-       else
-               IWL_WARN(priv, "uCode did not respond OK.\n");
-}
-
 static void iwl_bg_beacon_update(struct work_struct *work)
 {
        struct iwl_priv *priv =
@@ -524,12 +408,14 @@ 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->mutex);
+
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
+               goto out;
 
        /* dont send host command if rf-kill is on */
        if (!iwl_is_ready_rf(priv))
-               return;
+               goto out;
 
        IWL_DEBUG_INFO(priv, "BT coex in %s mode\n",
                       priv->bt_full_concurrent ?
@@ -539,15 +425,15 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
         * LQ & RXON updated cmds must be sent before BT Config cmd
         * to avoid 3-wire collisions
         */
-       mutex_lock(&priv->mutex);
        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);
        }
-       mutex_unlock(&priv->mutex);
 
        priv->cfg->ops->hcmd->send_bt_config(priv);
+out:
+       mutex_unlock(&priv->mutex);
 }
 
 /**
@@ -597,7 +483,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
        }
 
        /* Set starting address; reads will auto-increment */
-       _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
+       iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr);
        rmb();
 
        /*
@@ -605,13 +491,13 @@ 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_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+               ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
+               time = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
                if (mode == 0) {
                        trace_iwlwifi_dev_ucode_cont_event(priv,
                                                        0, time, ev);
                } else {
-                       data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+                       data = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
                        trace_iwlwifi_dev_ucode_cont_event(priv,
                                                time, data, ev);
                }
@@ -629,10 +515,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
        u32 num_wraps;  /* # times uCode wrapped to top of log */
        u32 next_entry; /* index of next entry to be written by uCode */
 
-       if (priv->ucode_type == UCODE_INIT)
-               base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
-       else
-               base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+       base = priv->device_pointers.error_event_table;
        if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
                capacity = iwl_read_targ_mem(priv, base);
                num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
@@ -699,83 +582,6 @@ static void iwl_bg_ucode_trace(unsigned long data)
        }
 }
 
-static void iwl_rx_beacon_notif(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl4965_beacon_notif *beacon =
-               (struct iwl4965_beacon_notif *)pkt->u.raw;
-#ifdef CONFIG_IWLWIFI_DEBUG
-       u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
-
-       IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
-               "tsf %d %d rate %d\n",
-               le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
-               beacon->beacon_notify_hdr.failure_frame,
-               le32_to_cpu(beacon->ibss_mgr_status),
-               le32_to_cpu(beacon->high_tsf),
-               le32_to_cpu(beacon->low_tsf), rate);
-#endif
-
-       priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
-
-       if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
-               queue_work(priv->workqueue, &priv->beacon_update);
-}
-
-/* Handle notification from uCode that card's power state is changing
- * due to software, hardware, or critical temperature RFKILL */
-static void iwl_rx_card_state_notif(struct iwl_priv *priv,
-                                   struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
-       unsigned long status = priv->status;
-
-       IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
-                         (flags & HW_CARD_DISABLED) ? "Kill" : "On",
-                         (flags & SW_CARD_DISABLED) ? "Kill" : "On",
-                         (flags & CT_CARD_DISABLED) ?
-                         "Reached" : "Not reached");
-
-       if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
-                    CT_CARD_DISABLED)) {
-
-               iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-                           CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-               iwl_write_direct32(priv, HBUS_TARG_MBX_C,
-                                       HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-
-               if (!(flags & RXON_CARD_DISABLED)) {
-                       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-                                   CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-                       iwl_write_direct32(priv, HBUS_TARG_MBX_C,
-                                       HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-               }
-               if (flags & CT_CARD_DISABLED)
-                       iwl_tt_enter_ct_kill(priv);
-       }
-       if (!(flags & CT_CARD_DISABLED))
-               iwl_tt_exit_ct_kill(priv);
-
-       if (flags & HW_CARD_DISABLED)
-               set_bit(STATUS_RF_KILL_HW, &priv->status);
-       else
-               clear_bit(STATUS_RF_KILL_HW, &priv->status);
-
-
-       if (!(flags & RXON_CARD_DISABLED))
-               iwl_scan_cancel(priv);
-
-       if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-            test_bit(STATUS_RF_KILL_HW, &priv->status)))
-               wiphy_rfkill_set_hw_state(priv->hw->wiphy,
-                       test_bit(STATUS_RF_KILL_HW, &priv->status));
-       else
-               wake_up_interruptible(&priv->wait_command_queue);
-}
-
 static void iwl_bg_tx_flush(struct work_struct *work)
 {
        struct iwl_priv *priv =
@@ -794,51 +600,6 @@ static void iwl_bg_tx_flush(struct work_struct *work)
        }
 }
 
-/**
- * iwl_setup_rx_handlers - Initialize Rx handler callbacks
- *
- * Setup the RX handlers for each of the reply types sent from the uCode
- * to the host.
- *
- * This function chains into the hardware specific files for them to setup
- * any hardware specific handlers as well.
- */
-static void iwl_setup_rx_handlers(struct iwl_priv *priv)
-{
-       priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
-       priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
-       priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
-       priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
-                       iwl_rx_spectrum_measure_notif;
-       priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
-       priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
-           iwl_rx_pm_debug_statistics_notif;
-       priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
-
-       /*
-        * The same handler is used for both the REPLY to a discrete
-        * statistics request from the host as well as for the periodic
-        * statistics notifications (after received beacons) from the uCode.
-        */
-       priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics;
-       priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
-
-       iwl_setup_rx_scan_handlers(priv);
-
-       /* status change handler */
-       priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
-
-       priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
-           iwl_rx_missed_beacon_notif;
-       /* Rx handlers */
-       priv->rx_handlers[REPLY_RX_PHY_CMD] = iwlagn_rx_reply_rx_phy;
-       priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwlagn_rx_reply_rx;
-       /* block ack */
-       priv->rx_handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba;
-       /* Set up hardware specific Rx handlers */
-       priv->cfg->ops->lib->rx_handler_setup(priv);
-}
-
 /**
  * iwl_rx_handle - Main entry function for receiving responses from uCode
  *
@@ -846,7 +607,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv)
  * the appropriate handlers, including command responses,
  * frame-received notifications, and other notifications.
  */
-void iwl_rx_handle(struct iwl_priv *priv)
+static void iwl_rx_handle(struct iwl_priv *priv)
 {
        struct iwl_rx_mem_buffer *rxb;
        struct iwl_rx_packet *pkt;
@@ -883,7 +644,10 @@ void iwl_rx_handle(struct iwl_priv *priv)
                /* If an RXB doesn't have a Rx queue slot associated with it,
                 * then a bug has been introduced in the queue refilling
                 * routines -- catch it here */
-               BUG_ON(rxb == NULL);
+               if (WARN_ON(rxb == NULL)) {
+                       i = (i + 1) & RX_QUEUE_MASK;
+                       continue;
+               }
 
                rxq->queue[i] = NULL;
 
@@ -910,6 +674,29 @@ void iwl_rx_handle(struct iwl_priv *priv)
                        (pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
                        (pkt->hdr.cmd != REPLY_TX);
 
+               /*
+                * Do the notification wait before RX handlers so
+                * even if the RX handler consumes the RXB we have
+                * access to it in the notification wait entry.
+                */
+               if (!list_empty(&priv->_agn.notif_waits)) {
+                       struct iwl_notification_wait *w;
+
+                       spin_lock(&priv->_agn.notif_wait_lock);
+                       list_for_each_entry(w, &priv->_agn.notif_waits, list) {
+                               if (w->cmd == pkt->hdr.cmd) {
+                                       w->triggered = true;
+                                       if (w->fn)
+                                               w->fn(priv, pkt, w->fn_data);
+                               }
+                       }
+                       spin_unlock(&priv->_agn.notif_wait_lock);
+
+                       wake_up_all(&priv->_agn.notif_waitq);
+               }
+               if (priv->pre_rx_handler)
+                       priv->pre_rx_handler(priv, rxb);
+
                /* Based on type of command response or notification,
                 *   handle those that need handling via function in
                 *   rx_handlers table.  See iwl_setup_rx_handlers() */
@@ -979,196 +766,6 @@ void iwl_rx_handle(struct iwl_priv *priv)
                iwlagn_rx_queue_restock(priv);
 }
 
-/* call this function to flush any scheduled tasklet */
-static inline void iwl_synchronize_irq(struct iwl_priv *priv)
-{
-       /* wait to make sure we flush pending tasklet*/
-       synchronize_irq(priv->pci_dev->irq);
-       tasklet_kill(&priv->irq_tasklet);
-}
-
-static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
-{
-       u32 inta, handled = 0;
-       u32 inta_fh;
-       unsigned long flags;
-       u32 i;
-#ifdef CONFIG_IWLWIFI_DEBUG
-       u32 inta_mask;
-#endif
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       /* Ack/clear/reset pending uCode interrupts.
-        * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
-        *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
-       inta = iwl_read32(priv, CSR_INT);
-       iwl_write32(priv, CSR_INT, inta);
-
-       /* Ack/clear/reset pending flow-handler (DMA) interrupts.
-        * Any new interrupts that happen after this, either while we're
-        * in this tasklet, or later, will show up in next ISR/tasklet. */
-       inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-       iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-       if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
-               /* just for debug */
-               inta_mask = iwl_read32(priv, CSR_INT_MASK);
-               IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-                             inta, inta_mask, inta_fh);
-       }
-#endif
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
-        * atomic, make sure that inta covers all the interrupts that
-        * we've discovered, even if FH interrupt came in just after
-        * reading CSR_INT. */
-       if (inta_fh & CSR49_FH_INT_RX_MASK)
-               inta |= CSR_INT_BIT_FH_RX;
-       if (inta_fh & CSR49_FH_INT_TX_MASK)
-               inta |= CSR_INT_BIT_FH_TX;
-
-       /* Now service all interrupt bits discovered above. */
-       if (inta & CSR_INT_BIT_HW_ERR) {
-               IWL_ERR(priv, "Hardware error detected.  Restarting.\n");
-
-               /* Tell the device to stop sending interrupts */
-               iwl_disable_interrupts(priv);
-
-               priv->isr_stats.hw++;
-               iwl_irq_handle_error(priv);
-
-               handled |= CSR_INT_BIT_HW_ERR;
-
-               return;
-       }
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-       if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
-               /* NIC fires this, but we don't use it, redundant with WAKEUP */
-               if (inta & CSR_INT_BIT_SCD) {
-                       IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
-                                     "the frame/frames.\n");
-                       priv->isr_stats.sch++;
-               }
-
-               /* Alive notification via Rx interrupt will do the real work */
-               if (inta & CSR_INT_BIT_ALIVE) {
-                       IWL_DEBUG_ISR(priv, "Alive interrupt\n");
-                       priv->isr_stats.alive++;
-               }
-       }
-#endif
-       /* Safely ignore these bits for debug checks below */
-       inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
-
-       /* HW RF KILL switch toggled */
-       if (inta & CSR_INT_BIT_RF_KILL) {
-               int hw_rf_kill = 0;
-               if (!(iwl_read32(priv, CSR_GP_CNTRL) &
-                               CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
-                       hw_rf_kill = 1;
-
-               IWL_WARN(priv, "RF_KILL bit toggled to %s.\n",
-                               hw_rf_kill ? "disable radio" : "enable radio");
-
-               priv->isr_stats.rfkill++;
-
-               /* driver only loads ucode once setting the interface up.
-                * the driver allows loading the ucode even if the radio
-                * is killed. Hence update the killswitch state here. The
-                * rfkill handler will care about restarting if needed.
-                */
-               if (!test_bit(STATUS_ALIVE, &priv->status)) {
-                       if (hw_rf_kill)
-                               set_bit(STATUS_RF_KILL_HW, &priv->status);
-                       else
-                               clear_bit(STATUS_RF_KILL_HW, &priv->status);
-                       wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
-               }
-
-               handled |= CSR_INT_BIT_RF_KILL;
-       }
-
-       /* Chip got too hot and stopped itself */
-       if (inta & CSR_INT_BIT_CT_KILL) {
-               IWL_ERR(priv, "Microcode CT kill error detected.\n");
-               priv->isr_stats.ctkill++;
-               handled |= CSR_INT_BIT_CT_KILL;
-       }
-
-       /* Error detected by uCode */
-       if (inta & CSR_INT_BIT_SW_ERR) {
-               IWL_ERR(priv, "Microcode SW error detected. "
-                       " Restarting 0x%X.\n", inta);
-               priv->isr_stats.sw++;
-               iwl_irq_handle_error(priv);
-               handled |= CSR_INT_BIT_SW_ERR;
-       }
-
-       /*
-        * uCode wakes up after power-down sleep.
-        * Tell device about any new tx or host commands enqueued,
-        * and about any Rx buffers made available while asleep.
-        */
-       if (inta & CSR_INT_BIT_WAKEUP) {
-               IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
-               iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
-               for (i = 0; i < priv->hw_params.max_txq_num; i++)
-                       iwl_txq_update_write_ptr(priv, &priv->txq[i]);
-               priv->isr_stats.wakeup++;
-               handled |= CSR_INT_BIT_WAKEUP;
-       }
-
-       /* All uCode command responses, including Tx command responses,
-        * Rx "responses" (frame-received notification), and other
-        * notifications from uCode come through here*/
-       if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
-               iwl_rx_handle(priv);
-               priv->isr_stats.rx++;
-               handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
-       }
-
-       /* This "Tx" DMA channel is used only for loading uCode */
-       if (inta & CSR_INT_BIT_FH_TX) {
-               IWL_DEBUG_ISR(priv, "uCode load interrupt\n");
-               priv->isr_stats.tx++;
-               handled |= CSR_INT_BIT_FH_TX;
-               /* Wake up uCode load routine, now that load is complete */
-               priv->ucode_write_complete = 1;
-               wake_up_interruptible(&priv->wait_command_queue);
-       }
-
-       if (inta & ~handled) {
-               IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
-               priv->isr_stats.unhandled++;
-       }
-
-       if (inta & ~(priv->inta_mask)) {
-               IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
-                        inta & ~priv->inta_mask);
-               IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
-       }
-
-       /* Re-enable all interrupts */
-       /* only Re-enable if diabled by irq */
-       if (test_bit(STATUS_INT_ENABLED, &priv->status))
-               iwl_enable_interrupts(priv);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-       if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
-               inta = iwl_read32(priv, CSR_INT);
-               inta_mask = iwl_read32(priv, CSR_INT_MASK);
-               inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-               IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
-                       "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
-       }
-#endif
-}
-
 /* tasklet for iwlagn interrupt */
 static void iwl_irq_tasklet(struct iwl_priv *priv)
 {
@@ -1310,7 +907,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
                if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
                        handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
                        iwl_write32(priv, CSR_FH_INT_STATUS,
-                                       CSR49_FH_INT_RX_MASK);
+                                       CSR_FH_INT_RX_MASK);
                }
                if (inta & CSR_INT_BIT_RX_PERIODIC) {
                        handled |= CSR_INT_BIT_RX_PERIODIC;
@@ -1348,7 +945,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
 
        /* This "Tx" DMA channel is used only for loading uCode */
        if (inta & CSR_INT_BIT_FH_TX) {
-               iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK);
+               iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK);
                IWL_DEBUG_ISR(priv, "uCode load interrupt\n");
                priv->isr_stats.tx++;
                handled |= CSR_INT_BIT_FH_TX;
@@ -1368,71 +965,14 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
        }
 
        /* Re-enable all interrupts */
-       /* only Re-enable if diabled by irq */
+       /* only Re-enable if disabled by irq */
        if (test_bit(STATUS_INT_ENABLED, &priv->status))
                iwl_enable_interrupts(priv);
+       /* Re-enable RF_KILL if it occurred */
+       else if (handled & CSR_INT_BIT_RF_KILL)
+               iwl_enable_rfkill_int(priv);
 }
 
-/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
-#define ACK_CNT_RATIO (50)
-#define BA_TIMEOUT_CNT (5)
-#define BA_TIMEOUT_MAX (16)
-
-/**
- * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries.
- *
- * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding
- * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
- * operation state.
- */
-bool iwl_good_ack_health(struct iwl_priv *priv,
-                               struct iwl_rx_packet *pkt)
-{
-       bool rc = true;
-       int actual_ack_cnt_delta, expected_ack_cnt_delta;
-       int ba_timeout_delta;
-
-       actual_ack_cnt_delta =
-               le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
-               le32_to_cpu(priv->_agn.statistics.tx.actual_ack_cnt);
-       expected_ack_cnt_delta =
-               le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) -
-               le32_to_cpu(priv->_agn.statistics.tx.expected_ack_cnt);
-       ba_timeout_delta =
-               le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) -
-               le32_to_cpu(priv->_agn.statistics.tx.agg.ba_timeout);
-       if ((priv->_agn.agg_tids_count > 0) &&
-           (expected_ack_cnt_delta > 0) &&
-           (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta)
-               < ACK_CNT_RATIO) &&
-           (ba_timeout_delta > BA_TIMEOUT_CNT)) {
-               IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d,"
-                               " expected_ack_cnt = %d\n",
-                               actual_ack_cnt_delta, expected_ack_cnt_delta);
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-               /*
-                * This is ifdef'ed on DEBUGFS because otherwise the
-                * statistics aren't available. If DEBUGFS is set but
-                * DEBUG is not, these will just compile out.
-                */
-               IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
-                               priv->_agn.delta_statistics.tx.rx_detected_cnt);
-               IWL_DEBUG_RADIO(priv,
-                               "ack_or_ba_timeout_collision delta = %d\n",
-                               priv->_agn.delta_statistics.tx.
-                               ack_or_ba_timeout_collision);
-#endif
-               IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
-                               ba_timeout_delta);
-               if (!actual_ack_cnt_delta &&
-                   (ba_timeout_delta >= BA_TIMEOUT_MAX))
-                       rc = false;
-       }
-       return rc;
-}
-
-
 /*****************************************************************************
  *
  * sysfs attributes
@@ -1553,26 +1093,48 @@ static struct attribute_group iwl_attribute_group = {
  *
  ******************************************************************************/
 
-static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
+static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
 {
-       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
-       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
-       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
-       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init);
-       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
-       iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
+       if (desc->v_addr)
+               dma_free_coherent(&pci_dev->dev, desc->len,
+                                 desc->v_addr, desc->p_addr);
+       desc->v_addr = NULL;
+       desc->len = 0;
 }
 
-static void iwl_nic_start(struct iwl_priv *priv)
+static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img)
 {
-       /* Remove all resets to allow NIC to operate */
-       iwl_write32(priv, CSR_RESET, 0);
+       iwl_free_fw_desc(pci_dev, &img->code);
+       iwl_free_fw_desc(pci_dev, &img->data);
+}
+
+static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
+                            const void *data, size_t len)
+{
+       if (!len) {
+               desc->v_addr = NULL;
+               return -EINVAL;
+       }
+
+       desc->v_addr = dma_alloc_coherent(&pci_dev->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;
-       bool pan;
+       u32 flags;
 };
 
 static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
@@ -1618,8 +1180,8 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
 }
 
 struct iwlagn_firmware_pieces {
-       const void *inst, *data, *init, *init_data, *boot;
-       size_t inst_size, data_size, init_size, init_data_size, boot_size;
+       const void *inst, *data, *init, *init_data;
+       size_t inst_size, data_size, init_size, init_data_size;
 
        u32 build;
 
@@ -1640,28 +1202,18 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
 
        switch (api_ver) {
        default:
-               /*
-                * 4965 doesn't revision the firmware file format
-                * along with the API version, it always uses v1
-                * file format.
-                */
-               if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) !=
-                               CSR_HW_REV_TYPE_4965) {
-                       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);
-                       pieces->boot_size = le32_to_cpu(ucode->u.v2.boot_size);
-                       src = ucode->u.v2.data;
-                       break;
+               hdr_size = 28;
+               if (ucode_raw->size < hdr_size) {
+                       IWL_ERR(priv, "File size too small!\n");
+                       return -EINVAL;
                }
-               /* fall through for 4965 */
+               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:
@@ -1675,7 +1227,6 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
                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);
-               pieces->boot_size = le32_to_cpu(ucode->u.v1.boot_size);
                src = ucode->u.v1.data;
                break;
        }
@@ -1683,7 +1234,7 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
        /* 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 + pieces->boot_size) {
+                               pieces->init_data_size) {
 
                IWL_ERR(priv,
                        "uCode file size %d does not match expected size\n",
@@ -1699,8 +1250,6 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
        src += pieces->init_size;
        pieces->init_data = src;
        src += pieces->init_data_size;
-       pieces->boot = src;
-       src += pieces->boot_size;
 
        return 0;
 }
@@ -1801,8 +1350,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
                        pieces->init_data_size = tlv_len;
                        break;
                case IWL_UCODE_TLV_BOOT:
-                       pieces->boot = tlv_data;
-                       pieces->boot_size = tlv_len;
+                       IWL_ERR(priv, "Found unexpected BOOT ucode\n");
                        break;
                case IWL_UCODE_TLV_PROBE_MAX_LEN:
                        if (tlv_len != sizeof(u32))
@@ -1813,7 +1361,23 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
                case IWL_UCODE_TLV_PAN:
                        if (tlv_len)
                                goto invalid_tlv_len;
-                       capa->pan = true;
+                       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))
@@ -1863,7 +1427,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
                                        le32_to_cpup((__le32 *)tlv_data);
                        break;
                default:
-                       IWL_WARN(priv, "unknown TLV: %d\n", tlv_type);
+                       IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type);
                        break;
                }
        }
@@ -2002,8 +1566,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
                       pieces.init_size);
        IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n",
                       pieces.init_data_size);
-       IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %Zd\n",
-                      pieces.boot_size);
 
        /* Verify that uCode images will fit in card's SRAM */
        if (pieces.inst_size > priv->hw_params.max_inst_size) {
@@ -2030,48 +1592,25 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
                goto try_again;
        }
 
-       if (pieces.boot_size > priv->hw_params.max_bsm_size) {
-               IWL_ERR(priv, "uCode boot instr len %Zd too large to fit in\n",
-                       pieces.boot_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 */
-       priv->ucode_code.len = pieces.inst_size;
-       iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
-
-       priv->ucode_data.len = pieces.data_size;
-       iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
-
-       priv->ucode_data_backup.len = pieces.data_size;
-       iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
-
-       if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
-           !priv->ucode_data_backup.v_addr)
+       if (iwl_alloc_fw_desc(priv->pci_dev, &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,
+                             pieces.data, pieces.data_size))
                goto err_pci_alloc;
 
        /* Initialization instructions and data */
        if (pieces.init_size && pieces.init_data_size) {
-               priv->ucode_init.len = pieces.init_size;
-               iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
-
-               priv->ucode_init_data.len = pieces.init_data_size;
-               iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
-
-               if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
+               if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code,
+                                     pieces.init, pieces.init_size))
                        goto err_pci_alloc;
-       }
-
-       /* Bootstrap (instructions only, no data) */
-       if (pieces.boot_size) {
-               priv->ucode_boot.len = pieces.boot_size;
-               iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
-
-               if (!priv->ucode_boot.v_addr)
+               if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data,
+                                     pieces.init_data, pieces.init_data_size))
                        goto err_pci_alloc;
        }
 
@@ -2097,50 +1636,19 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
                        priv->cfg->base_params->max_event_log_size;
        priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr;
 
-       if (ucode_capa.pan) {
+       priv->new_scan_threshold_behaviour =
+               !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
+
+       if (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
                priv->sta_key_max_num = STA_KEY_MAX_NUM;
 
-       /* Copy images into buffers for card's bus-master reads ... */
-
-       /* Runtime instructions (first block of data in file) */
-       IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n",
-                       pieces.inst_size);
-       memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size);
-
-       IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
-               priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
-
-       /*
-        * Runtime data
-        * NOTE:  Copy into backup buffer will be done in iwl_up()
-        */
-       IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n",
-                       pieces.data_size);
-       memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size);
-       memcpy(priv->ucode_data_backup.v_addr, pieces.data, pieces.data_size);
-
-       /* Initialization instructions */
-       if (pieces.init_size) {
-               IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n",
-                               pieces.init_size);
-               memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size);
-       }
-
-       /* Initialization data */
-       if (pieces.init_data_size) {
-               IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n",
-                              pieces.init_data_size);
-               memcpy(priv->ucode_init_data.v_addr, pieces.init_data,
-                      pieces.init_data_size);
-       }
-
-       /* Bootstrap instructions */
-       IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n",
-                       pieces.boot_size);
-       memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size);
+       if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
+               priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
+       else
+               priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
 
        /*
         * figure out the offset of chain noise reset and gain commands
@@ -2258,7 +1766,7 @@ static const char *desc_lookup(u32 num)
        max = ARRAY_SIZE(advanced_lookup) - 1;
        for (i = 0; i < max; i++) {
                if (advanced_lookup[i].num == num)
-                       break;;
+                       break;
        }
        return advanced_lookup[i].name;
 }
@@ -2272,13 +1780,13 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
        u32 desc, time, count, base, data1;
        u32 blink1, blink2, ilink1, ilink2;
        u32 pc, hcmd;
+       struct iwl_error_event_table table;
 
-       if (priv->ucode_type == UCODE_INIT) {
-               base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
+       base = priv->device_pointers.error_event_table;
+       if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
                if (!base)
                        base = priv->_agn.init_errlog_ptr;
        } else {
-               base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
                if (!base)
                        base = priv->_agn.inst_errlog_ptr;
        }
@@ -2286,11 +1794,15 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
        if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
                IWL_ERR(priv,
                        "Not valid error log pointer 0x%08X for %s uCode\n",
-                       base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
+                       base,
+                       (priv->ucode_type == UCODE_SUBTYPE_INIT)
+                                       ? "Init" : "RT");
                return;
        }
 
-       count = iwl_read_targ_mem(priv, base);
+       iwl_read_targ_mem_words(priv, base, &table, sizeof(table));
+
+       count = table.valid;
 
        if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
                IWL_ERR(priv, "Start IWL Error Log Dump:\n");
@@ -2298,18 +1810,18 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
                        priv->status, count);
        }
 
-       desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
+       desc = table.error_id;
        priv->isr_stats.err_code = desc;
-       pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32));
-       blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
-       blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
-       ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
-       ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
-       data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
-       data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
-       line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
-       time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
-       hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32));
+       pc = table.pc;
+       blink1 = table.blink1;
+       blink2 = table.blink2;
+       ilink1 = table.ilink1;
+       ilink2 = table.ilink2;
+       data1 = table.data1;
+       data2 = table.data2;
+       line = table.line;
+       time = table.tsf_low;
+       hcmd = table.hcmd;
 
        trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line,
                                      blink1, blink2, ilink1, ilink2);
@@ -2343,12 +1855,11 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
        if (num_events == 0)
                return pos;
 
-       if (priv->ucode_type == UCODE_INIT) {
-               base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+       base = priv->device_pointers.log_event_table;
+       if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
                if (!base)
                        base = priv->_agn.init_evtlog_ptr;
        } else {
-               base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
                if (!base)
                        base = priv->_agn.inst_evtlog_ptr;
        }
@@ -2365,14 +1876,14 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
        iwl_grab_nic_access(priv);
 
        /* Set starting address; reads will auto-increment */
-       _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
+       iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr);
        rmb();
 
        /* "time" is actually "data" for mode 0 (no timestamp).
        * place event id # at far right for easier visual parsing. */
        for (i = 0; i < num_events; i++) {
-               ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+               ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
+               time = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
                if (mode == 0) {
                        /* data, ev */
                        if (bufsz) {
@@ -2386,7 +1897,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
                                        time, ev);
                        }
                } else {
-                       data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+                       data = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
                        if (bufsz) {
                                pos += scnprintf(*buf + pos, bufsz - pos,
                                                "EVT_LOGT:%010u:0x%08x:%04u\n",
@@ -2457,13 +1968,12 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
        int pos = 0;
        size_t bufsz = 0;
 
-       if (priv->ucode_type == UCODE_INIT) {
-               base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+       base = priv->device_pointers.log_event_table;
+       if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
                logsize = priv->_agn.init_evtlog_size;
                if (!base)
                        base = priv->_agn.init_evtlog_ptr;
        } else {
-               base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
                logsize = priv->_agn.inst_evtlog_size;
                if (!base)
                        base = priv->_agn.inst_evtlog_ptr;
@@ -2472,7 +1982,9 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
        if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
                IWL_ERR(priv,
                        "Invalid event log pointer 0x%08X for %s uCode\n",
-                       base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
+                       base,
+                       (priv->ucode_type == UCODE_SUBTYPE_INIT)
+                                       ? "Init" : "RT");
                return -EINVAL;
        }
 
@@ -2502,7 +2014,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
                return pos;
        }
 
-       /* enable/disable bt channel announcement */
+       /* enable/disable bt channel inhibition */
        priv->bt_ch_announce = iwlagn_bt_ch_announce;
 
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -2619,51 +2131,23 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
  *                   from protocol/runtime uCode (initialization uCode's
  *                   Alive gets handled by iwl_init_alive_start()).
  */
-static void iwl_alive_start(struct iwl_priv *priv)
+int iwl_alive_start(struct iwl_priv *priv)
 {
        int ret = 0;
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
-       IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
-
-       if (priv->card_alive.is_valid != UCODE_VALID_OK) {
-               /* We had an error bringing up the hardware, so take it
-                * all the way back down so we can try again */
-               IWL_DEBUG_INFO(priv, "Alive failed.\n");
-               goto restart;
-       }
-
-       /* Initialize uCode has loaded Runtime uCode ... verify inst image.
-        * This is a paranoid check, because we would not have gotten the
-        * "runtime" alive if code weren't properly loaded.  */
-       if (iwl_verify_ucode(priv)) {
-               /* Runtime instruction load was bad;
-                * take it all the way back down so we can try again */
-               IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n");
-               goto restart;
-       }
-
-       ret = priv->cfg->ops->lib->alive_notify(priv);
-       if (ret) {
-               IWL_WARN(priv,
-                       "Could not complete ALIVE transition [ntf]: %d\n", ret);
-               goto restart;
-       }
+       iwl_reset_ict(priv);
 
+       IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
 
        /* After the ALIVE response, we can send host commands to the uCode */
        set_bit(STATUS_ALIVE, &priv->status);
 
-       if (priv->cfg->ops->lib->recover_from_tx_stall) {
-               /* Enable timer to monitor the driver queues */
-               mod_timer(&priv->monitor_recover,
-                       jiffies +
-                       msecs_to_jiffies(
-                         priv->cfg->base_params->monitor_recover_period));
-       }
+       /* Enable watchdog to monitor the driver tx queues */
+       iwl_setup_watchdog(priv);
 
        if (iwl_is_rfkill(priv))
-               return;
+               return -ERFKILL;
 
        /* download priority table before any calibration request */
        if (priv->cfg->bt_params &&
@@ -2677,10 +2161,14 @@ static void iwl_alive_start(struct iwl_priv *priv)
                iwlagn_send_prio_tbl(priv);
 
                /* FIXME: w/a to force change uCode BT state machine */
-               iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
-                       BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
-               iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
-                       BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+               ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
+                                        BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+               if (ret)
+                       return ret;
+               ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
+                                        BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+               if (ret)
+                       return ret;
        }
        if (priv->hw_params.calib_rt_cfg)
                iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
@@ -2709,9 +2197,11 @@ static void iwl_alive_start(struct iwl_priv *priv)
                        priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
        }
 
-       if (priv->cfg->bt_params &&
-           !priv->cfg->bt_params->advanced_bt_coexist) {
-               /* Configure Bluetooth device coexistence support */
+       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);
        }
 
@@ -2720,32 +2210,23 @@ static void iwl_alive_start(struct iwl_priv *priv)
        set_bit(STATUS_READY, &priv->status);
 
        /* Configure the adapter for unassociated operation */
-       iwlcore_commit_rxon(priv, ctx);
+       ret = iwlcore_commit_rxon(priv, ctx);
+       if (ret)
+               return ret;
 
        /* At this point, the NIC is initialized and operational */
        iwl_rf_kill_ct_config(priv);
 
-       iwl_leds_init(priv);
-
        IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
-       wake_up_interruptible(&priv->wait_command_queue);
-
-       iwl_power_update_mode(priv, true);
-       IWL_DEBUG_INFO(priv, "Updated power mode\n");
-
-
-       return;
 
- restart:
-       queue_work(priv->workqueue, &priv->restart);
+       return iwl_power_update_mode(priv, true);
 }
 
 static void iwl_cancel_deferred_work(struct iwl_priv *priv);
 
 static void __iwl_down(struct iwl_priv *priv)
 {
-       unsigned long flags;
-       int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
+       int exit_pending;
 
        IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
 
@@ -2755,8 +2236,7 @@ static void __iwl_down(struct iwl_priv *priv)
 
        /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
         * to prevent rearm timer */
-       if (priv->cfg->ops->lib->recover_from_tx_stall)
-               del_timer_sync(&priv->monitor_recover);
+       del_timer_sync(&priv->watchdog);
 
        iwl_clear_ucode_stations(priv, NULL);
        iwl_dealloc_bcast_stations(priv);
@@ -2769,44 +2249,18 @@ static void __iwl_down(struct iwl_priv *priv)
                         priv->cfg->bt_params->bt_init_traffic_load;
        else
                priv->bt_traffic_load = 0;
-       priv->bt_sco_active = false;
        priv->bt_full_concurrent = false;
        priv->bt_ci_compliance = 0;
 
-       /* Unblock any waiting calls */
-       wake_up_interruptible_all(&priv->wait_command_queue);
-
        /* Wipe out the EXIT_PENDING status bit if we are not actually
         * exiting the module */
        if (!exit_pending)
                clear_bit(STATUS_EXIT_PENDING, &priv->status);
 
-       /* stop and reset the on-board processor */
-       iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
-       /* tell the device to stop sending interrupts */
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_disable_interrupts(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-       iwl_synchronize_irq(priv);
-
        if (priv->mac80211_registered)
                ieee80211_stop_queues(priv->hw);
 
-       /* If we have not previously called iwl_init() then
-        * clear all bits but the RF Kill bit and return */
-       if (!iwl_is_init(priv)) {
-               priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
-                                       STATUS_RF_KILL_HW |
-                              test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
-                                       STATUS_GEO_CONFIGURED |
-                              test_bit(STATUS_EXIT_PENDING, &priv->status) <<
-                                       STATUS_EXIT_PENDING;
-               goto exit;
-       }
-
-       /* ...otherwise clear out all the status bits but the RF Kill
-        * bit and continue taking the NIC down. */
+       /* Clear out all status bits but a few that are stable across reset */
        priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
                                STATUS_RF_KILL_HW |
                        test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
@@ -2816,31 +2270,10 @@ static void __iwl_down(struct iwl_priv *priv)
                       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
                                STATUS_EXIT_PENDING;
 
-       /* device going down, Stop using ICT table */
-       if (priv->cfg->ops->lib->isr_ops.disable)
-               priv->cfg->ops->lib->isr_ops.disable(priv);
-
-       iwlagn_txq_ctx_stop(priv);
-       iwlagn_rxq_stop(priv);
-
-       /* Power-down device's busmaster DMA clocks */
-       iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
-       udelay(5);
-
-       /* Make sure (redundant) we've released our request to stay awake */
-       iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
-       /* Stop the device, and put it in low power state */
-       iwl_apm_stop(priv);
-
- exit:
-       memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
+       iwlagn_stop_device(priv);
 
        dev_kfree_skb(priv->beacon_skb);
        priv->beacon_skb = NULL;
-
-       /* clear out any free frames */
-       iwl_clear_free_frames(priv);
 }
 
 static void iwl_down(struct iwl_priv *priv)
@@ -2854,9 +2287,10 @@ static void iwl_down(struct iwl_priv *priv)
 
 #define HW_READY_TIMEOUT (50)
 
+/* Note: returns poll_bit return value, which is >= 0 if success */
 static int iwl_set_hw_ready(struct iwl_priv *priv)
 {
-       int ret = 0;
+       int ret;
 
        iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
                CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
@@ -2866,25 +2300,21 @@ static int iwl_set_hw_ready(struct iwl_priv *priv)
                                CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
                                CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
                                HW_READY_TIMEOUT);
-       if (ret != -ETIMEDOUT)
-               priv->hw_ready = true;
-       else
-               priv->hw_ready = false;
 
-       IWL_DEBUG_INFO(priv, "hardware %s\n",
-                     (priv->hw_ready == 1) ? "ready" : "not ready");
+       IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : "");
        return ret;
 }
 
-static int iwl_prepare_card_hw(struct iwl_priv *priv)
+/* Note: returns standard 0/-ERROR code */
+int iwl_prepare_card_hw(struct iwl_priv *priv)
 {
-       int ret = 0;
+       int ret;
 
        IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n");
 
        ret = iwl_set_hw_ready(priv);
-       if (priv->hw_ready)
-               return ret;
+       if (ret >= 0)
+               return 0;
 
        /* If HW is not ready, prepare the conditions to check again */
        iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
@@ -2892,124 +2322,67 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv)
 
        ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
                        ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
-                       CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
-
-       /* HW should be ready by now, check again. */
-       if (ret != -ETIMEDOUT)
-               iwl_set_hw_ready(priv);
-
-       return ret;
-}
-
-#define MAX_HW_RESTARTS 5
-
-static int __iwl_up(struct iwl_priv *priv)
-{
-       struct iwl_rxon_context *ctx;
-       int i;
-       int ret;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-               IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
-               return -EIO;
-       }
-
-       if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
-               IWL_ERR(priv, "ucode not available for device bringup\n");
-               return -EIO;
-       }
-
-       for_each_context(priv, ctx) {
-               ret = iwlagn_alloc_bcast_station(priv, ctx);
-               if (ret) {
-                       iwl_dealloc_bcast_stations(priv);
-                       return ret;
-               }
-       }
-
-       iwl_prepare_card_hw(priv);
-
-       if (!priv->hw_ready) {
-               IWL_WARN(priv, "Exit HW not ready\n");
-               return -EIO;
-       }
-
-       /* If platform's RF_KILL switch is NOT set to KILL */
-       if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
-               clear_bit(STATUS_RF_KILL_HW, &priv->status);
-       else
-               set_bit(STATUS_RF_KILL_HW, &priv->status);
-
-       if (iwl_is_rfkill(priv)) {
-               wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
-
-               iwl_enable_interrupts(priv);
-               IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
-               return 0;
-       }
-
-       iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-
-       /* must be initialised before iwl_hw_nic_init */
-       if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
-               priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
-       else
-               priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
-
-       ret = iwlagn_hw_nic_init(priv);
-       if (ret) {
-               IWL_ERR(priv, "Unable to init nic\n");
-               return ret;
-       }
+                       CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
 
-       /* make sure rfkill handshake bits are cleared */
-       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-                   CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+       if (ret < 0)
+               return ret;
 
-       /* clear (again), then enable host interrupts */
-       iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-       iwl_enable_interrupts(priv);
+       /* HW should be ready by now, check again. */
+       ret = iwl_set_hw_ready(priv);
+       if (ret >= 0)
+               return 0;
+       return ret;
+}
 
-       /* really make sure rfkill handshake bits are cleared */
-       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+#define MAX_HW_RESTARTS 5
 
-       /* Copy original ucode data image from disk into backup cache.
-        * This will be used to initialize the on-board processor's
-        * data SRAM for a clean start when the runtime program first loads. */
-       memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
-              priv->ucode_data.len);
+static int __iwl_up(struct iwl_priv *priv)
+{
+       struct iwl_rxon_context *ctx;
+       int ret;
 
-       for (i = 0; i < MAX_HW_RESTARTS; i++) {
+       lockdep_assert_held(&priv->mutex);
 
-               /* load bootstrap state machine,
-                * load bootstrap program into processor's memory,
-                * prepare to load the "initialize" uCode */
-               ret = priv->cfg->ops->lib->load_ucode(priv);
+       if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+               IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
+               return -EIO;
+       }
 
+       for_each_context(priv, ctx) {
+               ret = iwlagn_alloc_bcast_station(priv, ctx);
                if (ret) {
-                       IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n",
-                               ret);
-                       continue;
+                       iwl_dealloc_bcast_stations(priv);
+                       return ret;
                }
+       }
 
-               /* start card; "initialize" will load runtime ucode */
-               iwl_nic_start(priv);
-
-               IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
+       ret = iwlagn_run_init_ucode(priv);
+       if (ret) {
+               IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret);
+               goto error;
+       }
 
-               return 0;
+       ret = iwlagn_load_ucode_wait_alive(priv,
+                                          &priv->ucode_rt,
+                                          UCODE_SUBTYPE_REGULAR,
+                                          UCODE_SUBTYPE_REGULAR_NEW);
+       if (ret) {
+               IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
+               goto error;
        }
 
+       ret = iwl_alive_start(priv);
+       if (ret)
+               goto error;
+       return 0;
+
+ error:
        set_bit(STATUS_EXIT_PENDING, &priv->status);
        __iwl_down(priv);
        clear_bit(STATUS_EXIT_PENDING, &priv->status);
 
-       /* tried to restart and config the device for as long as our
-        * patience could withstand */
-       IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
-       return -EIO;
+       IWL_ERR(priv, "Unable to initialize device.\n");
+       return ret;
 }
 
 
@@ -3019,36 +2392,6 @@ static int __iwl_up(struct iwl_priv *priv)
  *
  *****************************************************************************/
 
-static void iwl_bg_init_alive_start(struct work_struct *data)
-{
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, init_alive_start.work);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       mutex_lock(&priv->mutex);
-       priv->cfg->ops->lib->init_alive_start(priv);
-       mutex_unlock(&priv->mutex);
-}
-
-static void iwl_bg_alive_start(struct work_struct *data)
-{
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, alive_start.work);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       /* enable dram interrupt */
-       if (priv->cfg->ops->lib->isr_ops.reset)
-               priv->cfg->ops->lib->isr_ops.reset(priv);
-
-       mutex_lock(&priv->mutex);
-       iwl_alive_start(priv);
-       mutex_unlock(&priv->mutex);
-}
-
 static void iwl_bg_run_time_calib_work(struct work_struct *work)
 {
        struct iwl_priv *priv = container_of(work, struct iwl_priv,
@@ -3063,23 +2406,49 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
        }
 
        if (priv->start_calib) {
-               if (priv->cfg->bt_params &&
-                   priv->cfg->bt_params->bt_statistics) {
-                       iwl_chain_noise_calibration(priv,
-                                       (void *)&priv->_agn.statistics_bt);
-                       iwl_sensitivity_calibration(priv,
-                                       (void *)&priv->_agn.statistics_bt);
-               } else {
-                       iwl_chain_noise_calibration(priv,
-                                       (void *)&priv->_agn.statistics);
-                       iwl_sensitivity_calibration(priv,
-                                       (void *)&priv->_agn.statistics);
-               }
+               iwl_chain_noise_calibration(priv);
+               iwl_sensitivity_calibration(priv);
        }
 
        mutex_unlock(&priv->mutex);
 }
 
+static void iwlagn_prepare_restart(struct iwl_priv *priv)
+{
+       struct iwl_rxon_context *ctx;
+       bool bt_full_concurrent;
+       u8 bt_ci_compliance;
+       u8 bt_load;
+       u8 bt_status;
+
+       lockdep_assert_held(&priv->mutex);
+
+       for_each_context(priv, ctx)
+               ctx->vif = NULL;
+       priv->is_open = 0;
+
+       /*
+        * __iwl_down() will clear the BT status variables,
+        * which is correct, but when we restart we really
+        * want to keep them so restore them afterwards.
+        *
+        * The restart process will later pick them up and
+        * re-configure the hw when we reconfigure the BT
+        * command.
+        */
+       bt_full_concurrent = priv->bt_full_concurrent;
+       bt_ci_compliance = priv->bt_ci_compliance;
+       bt_load = priv->bt_traffic_load;
+       bt_status = priv->bt_status;
+
+       __iwl_down(priv);
+
+       priv->bt_full_concurrent = bt_full_concurrent;
+       priv->bt_ci_compliance = bt_ci_compliance;
+       priv->bt_traffic_load = bt_load;
+       priv->bt_status = bt_status;
+}
+
 static void iwl_bg_restart(struct work_struct *data)
 {
        struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
@@ -3088,52 +2457,13 @@ static void iwl_bg_restart(struct work_struct *data)
                return;
 
        if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
-               struct iwl_rxon_context *ctx;
-               bool bt_sco, bt_full_concurrent;
-               u8 bt_ci_compliance;
-               u8 bt_load;
-               u8 bt_status;
-
                mutex_lock(&priv->mutex);
-               for_each_context(priv, ctx)
-                       ctx->vif = NULL;
-               priv->is_open = 0;
-
-               /*
-                * __iwl_down() will clear the BT status variables,
-                * which is correct, but when we restart we really
-                * want to keep them so restore them afterwards.
-                *
-                * The restart process will later pick them up and
-                * re-configure the hw when we reconfigure the BT
-                * command.
-                */
-               bt_sco = priv->bt_sco_active;
-               bt_full_concurrent = priv->bt_full_concurrent;
-               bt_ci_compliance = priv->bt_ci_compliance;
-               bt_load = priv->bt_traffic_load;
-               bt_status = priv->bt_status;
-
-               __iwl_down(priv);
-
-               priv->bt_sco_active = bt_sco;
-               priv->bt_full_concurrent = bt_full_concurrent;
-               priv->bt_ci_compliance = bt_ci_compliance;
-               priv->bt_traffic_load = bt_load;
-               priv->bt_status = bt_status;
-
+               iwlagn_prepare_restart(priv);
                mutex_unlock(&priv->mutex);
                iwl_cancel_deferred_work(priv);
                ieee80211_restart_hw(priv->hw);
        } else {
-               iwl_down(priv);
-
-               if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-                       return;
-
-               mutex_lock(&priv->mutex);
-               __iwl_up(priv);
-               mutex_unlock(&priv->mutex);
+               WARN_ON(1);
        }
 }
 
@@ -3150,14 +2480,100 @@ static void iwl_bg_rx_replenish(struct work_struct *data)
        mutex_unlock(&priv->mutex);
 }
 
+static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+                                struct ieee80211_channel *chan,
+                                enum nl80211_channel_type channel_type,
+                                unsigned int wait)
+{
+       struct iwl_priv *priv = hw->priv;
+       int ret;
+
+       /* Not supported if we don't have PAN */
+       if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) {
+               ret = -EOPNOTSUPP;
+               goto free;
+       }
+
+       /* Not supported on pre-P2P firmware */
+       if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes &
+                                       BIT(NL80211_IFTYPE_P2P_CLIENT))) {
+               ret = -EOPNOTSUPP;
+               goto free;
+       }
+
+       mutex_lock(&priv->mutex);
+
+       if (!priv->contexts[IWL_RXON_CTX_PAN].is_active) {
+               /*
+                * If the PAN context is free, use the normal
+                * way of doing remain-on-channel offload + TX.
+                */
+               ret = 1;
+               goto out;
+       }
+
+       /* TODO: queue up if scanning? */
+       if (test_bit(STATUS_SCANNING, &priv->status) ||
+           priv->_agn.offchan_tx_skb) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       /*
+        * max_scan_ie_len doesn't include the blank SSID or the header,
+        * so need to add that again here.
+        */
+       if (skb->len > hw->wiphy->max_scan_ie_len + 24 + 2) {
+               ret = -ENOBUFS;
+               goto out;
+       }
+
+       priv->_agn.offchan_tx_skb = skb;
+       priv->_agn.offchan_tx_timeout = wait;
+       priv->_agn.offchan_tx_chan = chan;
+
+       ret = iwl_scan_initiate(priv, priv->contexts[IWL_RXON_CTX_PAN].vif,
+                               IWL_SCAN_OFFCH_TX, chan->band);
+       if (ret)
+               priv->_agn.offchan_tx_skb = NULL;
+ out:
+       mutex_unlock(&priv->mutex);
+ free:
+       if (ret < 0)
+               kfree_skb(skb);
+
+       return ret;
+}
+
+static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw)
+{
+       struct iwl_priv *priv = hw->priv;
+       int ret;
+
+       mutex_lock(&priv->mutex);
+
+       if (!priv->_agn.offchan_tx_skb) {
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       priv->_agn.offchan_tx_skb = NULL;
+
+       ret = iwl_scan_cancel_timeout(priv, 200);
+       if (ret)
+               ret = -EIO;
+unlock:
+       mutex_unlock(&priv->mutex);
+
+       return ret;
+}
+
 /*****************************************************************************
  *
  * mac80211 entry point functions
  *
  *****************************************************************************/
 
-#define UCODE_READY_TIMEOUT    (4 * HZ)
-
 /*
  * Not a mac80211 entry point function, but it fits in with all the
  * other mac80211 functions grouped here.
@@ -3178,14 +2594,18 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
                    IEEE80211_HW_SPECTRUM_MGMT |
                    IEEE80211_HW_REPORTS_TX_ACK_STATUS;
 
-       if (!priv->cfg->base_params->broken_powersave)
-               hw->flags |= IEEE80211_HW_SUPPORTS_PS |
-                            IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
+       hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+
+       hw->flags |= IEEE80211_HW_SUPPORTS_PS |
+                    IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
        if (priv->cfg->sku & IWL_SKU_N)
                hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
                             IEEE80211_HW_SUPPORTS_STATIC_SMPS;
 
+       if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP)
+               hw->flags |= IEEE80211_HW_MFP_CAPABLE;
+
        hw->sta_data_size = sizeof(struct iwl_station_priv);
        hw->vif_data_size = sizeof(struct iwl_vif_priv);
 
@@ -3194,8 +2614,11 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
                hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
        }
 
+       hw->wiphy->max_remain_on_channel_duration = 1000;
+
        hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
-                           WIPHY_FLAG_DISABLE_BEACON_HINTS;
+                           WIPHY_FLAG_DISABLE_BEACON_HINTS |
+                           WIPHY_FLAG_IBSS_RSN;
 
        /*
         * For now, disable PS by default because it affects
@@ -3219,6 +2642,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
                priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
                        &priv->bands[IEEE80211_BAND_5GHZ];
 
+       iwl_leds_init(priv);
+
        ret = ieee80211_register_hw(priv->hw);
        if (ret) {
                IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
@@ -3230,7 +2655,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
 }
 
 
-int iwlagn_mac_start(struct ieee80211_hw *hw)
+static int iwlagn_mac_start(struct ieee80211_hw *hw)
 {
        struct iwl_priv *priv = hw->priv;
        int ret;
@@ -3241,37 +2666,23 @@ int iwlagn_mac_start(struct ieee80211_hw *hw)
        mutex_lock(&priv->mutex);
        ret = __iwl_up(priv);
        mutex_unlock(&priv->mutex);
-
        if (ret)
                return ret;
 
-       if (iwl_is_rfkill(priv))
-               goto out;
-
        IWL_DEBUG_INFO(priv, "Start UP work done.\n");
 
-       /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
-        * mac80211 will not be run successfully. */
-       ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-                       test_bit(STATUS_READY, &priv->status),
-                       UCODE_READY_TIMEOUT);
-       if (!ret) {
-               if (!test_bit(STATUS_READY, &priv->status)) {
-                       IWL_ERR(priv, "START_ALIVE timeout after %dms.\n",
-                               jiffies_to_msecs(UCODE_READY_TIMEOUT));
-                       return -ETIMEDOUT;
-               }
-       }
+       /* Now we should be done, and the READY bit should be set. */
+       if (WARN_ON(!test_bit(STATUS_READY, &priv->status)))
+               ret = -EIO;
 
-       iwl_led_start(priv);
+       iwlagn_led_enable(priv);
 
-out:
        priv->is_open = 1;
        IWL_DEBUG_MAC80211(priv, "leave\n");
        return 0;
 }
 
-void iwlagn_mac_stop(struct ieee80211_hw *hw)
+static void iwlagn_mac_stop(struct ieee80211_hw *hw)
 {
        struct iwl_priv *priv = hw->priv;
 
@@ -3286,14 +2697,15 @@ void iwlagn_mac_stop(struct ieee80211_hw *hw)
 
        flush_workqueue(priv->workqueue);
 
-       /* enable interrupts again in order to receive rfkill changes */
+       /* User space software may expect getting rfkill changes
+        * even if interface is down */
        iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-       iwl_enable_interrupts(priv);
+       iwl_enable_rfkill_int(priv);
 
        IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct iwl_priv *priv = hw->priv;
 
@@ -3306,14 +2718,13 @@ int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
                dev_kfree_skb_any(skb);
 
        IWL_DEBUG_MACDUMP(priv, "leave\n");
-       return NETDEV_TX_OK;
 }
 
-void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
-                               struct ieee80211_vif *vif,
-                               struct ieee80211_key_conf *keyconf,
-                               struct ieee80211_sta *sta,
-                               u32 iv32, u16 *phase1key)
+static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif,
+                                      struct ieee80211_key_conf *keyconf,
+                                      struct ieee80211_sta *sta,
+                                      u32 iv32, u16 *phase1key)
 {
        struct iwl_priv *priv = hw->priv;
        struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
@@ -3326,9 +2737,10 @@ void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
        IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-                      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-                      struct ieee80211_key_conf *key)
+static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+                             struct ieee80211_vif *vif,
+                             struct ieee80211_sta *sta,
+                             struct ieee80211_key_conf *key)
 {
        struct iwl_priv *priv = hw->priv;
        struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
@@ -3339,11 +2751,19 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
        IWL_DEBUG_MAC80211(priv, "enter\n");
 
-       if (priv->cfg->mod_params->sw_crypto) {
+       if (iwlagn_mod_params.sw_crypto) {
                IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
                return -EOPNOTSUPP;
        }
 
+       /*
+        * To support IBSS RSN, don't program group keys in IBSS, the
+        * hardware will then not attempt to decrypt the frames.
+        */
+       if (vif->type == NL80211_IFTYPE_ADHOC &&
+           !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+               return -EOPNOTSUPP;
+
        sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
        if (sta_id == IWL_INVALID_STATION)
                return -EINVAL;
@@ -3395,13 +2815,15 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        return ret;
 }
 
-int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
-                           struct ieee80211_vif *vif,
-                           enum ieee80211_ampdu_mlme_action action,
-                           struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif,
+                                  enum ieee80211_ampdu_mlme_action action,
+                                  struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+                                  u8 buf_size)
 {
        struct iwl_priv *priv = hw->priv;
        int ret = -EINVAL;
+       struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
 
        IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
                     sta->addr, tid);
@@ -3456,11 +2878,32 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
                }
                break;
        case IEEE80211_AMPDU_TX_OPERATIONAL:
+               buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
+
+               iwlagn_txq_agg_queue_setup(priv, sta, tid, buf_size);
+
+               /*
+                * If the limit is 0, then it wasn't initialised yet,
+                * use the default. We can do that since we take the
+                * minimum below, and we don't want to go above our
+                * default due to hardware restrictions.
+                */
+               if (sta_priv->max_agg_bufsize == 0)
+                       sta_priv->max_agg_bufsize =
+                               LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+
+               /*
+                * Even though in theory the peer could have different
+                * aggregation reorder buffer sizes for different sessions,
+                * our ucode doesn't allow for that and has a global limit
+                * for each station. Therefore, use the minimum of all the
+                * aggregation sessions and our default value.
+                */
+               sta_priv->max_agg_bufsize =
+                       min(sta_priv->max_agg_bufsize, buf_size);
+
                if (priv->cfg->ht_params &&
                    priv->cfg->ht_params->use_rts_for_aggregation) {
-                       struct iwl_station_priv *sta_priv =
-                               (void *) sta->drv_priv;
-
                        /*
                         * switch to RTS/CTS if it is the prefer protection
                         * method for HT traffic
@@ -3468,9 +2911,13 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 
                        sta_priv->lq_sta.lq.general_params.flags |=
                                LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
-                       iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
-                                       &sta_priv->lq_sta.lq, CMD_ASYNC, false);
                }
+
+               sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
+                       sta_priv->max_agg_bufsize;
+
+               iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
+                               &sta_priv->lq_sta.lq, CMD_ASYNC, false);
                ret = 0;
                break;
        }
@@ -3479,9 +2926,9 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
        return ret;
 }
 
-int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
-                      struct ieee80211_vif *vif,
-                      struct ieee80211_sta *sta)
+static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
+                             struct ieee80211_vif *vif,
+                             struct ieee80211_sta *sta)
 {
        struct iwl_priv *priv = hw->priv;
        struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
@@ -3522,8 +2969,8 @@ int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
        return 0;
 }
 
-void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
-                              struct ieee80211_channel_switch *ch_switch)
+static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
+                               struct ieee80211_channel_switch *ch_switch)
 {
        struct iwl_priv *priv = hw->priv;
        const struct iwl_channel_info *ch_info;
@@ -3544,21 +2991,22 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
 
        IWL_DEBUG_MAC80211(priv, "enter\n");
 
+       mutex_lock(&priv->mutex);
+
        if (iwl_is_rfkill(priv))
-               goto out_exit;
+               goto out;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
            test_bit(STATUS_SCANNING, &priv->status))
-               goto out_exit;
+               goto out;
 
        if (!iwl_is_associated_ctx(ctx))
-               goto out_exit;
+               goto out;
 
        /* channel switch in progress */
        if (priv->switch_rxon.switch_in_progress == true)
-               goto out_exit;
+               goto out;
 
-       mutex_lock(&priv->mutex);
        if (priv->cfg->ops->lib->set_channel_switch) {
 
                ch = channel->hw_value;
@@ -3614,16 +3062,15 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
        }
 out:
        mutex_unlock(&priv->mutex);
-out_exit:
        if (!priv->switch_rxon.switch_in_progress)
                ieee80211_chswitch_done(ctx->vif, false);
        IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-void iwlagn_configure_filter(struct ieee80211_hw *hw,
-                            unsigned int changed_flags,
-                            unsigned int *total_flags,
-                            u64 multicast)
+static void iwlagn_configure_filter(struct ieee80211_hw *hw,
+                                   unsigned int changed_flags,
+                                   unsigned int *total_flags,
+                                   u64 multicast)
 {
        struct iwl_priv *priv = hw->priv;
        __le32 filter_or = 0, filter_nand = 0;
@@ -3640,7 +3087,8 @@ void iwlagn_configure_filter(struct ieee80211_hw *hw,
                        changed_flags, *total_flags);
 
        CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
-       CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
+       /* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */
+       CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
        CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
 
 #undef CHK
@@ -3669,7 +3117,7 @@ void iwlagn_configure_filter(struct ieee80211_hw *hw,
                        FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
 }
 
-void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
+static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
 {
        struct iwl_priv *priv = hw->priv;
 
@@ -3707,6 +3155,95 @@ done:
        IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
+static void iwlagn_disable_roc(struct iwl_priv *priv)
+{
+       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
+       struct ieee80211_channel *chan = ACCESS_ONCE(priv->hw->conf.channel);
+
+       lockdep_assert_held(&priv->mutex);
+
+       if (!ctx->is_active)
+               return;
+
+       ctx->staging.dev_type = RXON_DEV_TYPE_2STA;
+       ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+       iwl_set_rxon_channel(priv, chan, ctx);
+       iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
+
+       priv->_agn.hw_roc_channel = NULL;
+
+       iwlcore_commit_rxon(priv, ctx);
+
+       ctx->is_active = false;
+}
+
+static void iwlagn_bg_roc_done(struct work_struct *work)
+{
+       struct iwl_priv *priv = container_of(work, struct iwl_priv,
+                                            _agn.hw_roc_work.work);
+
+       mutex_lock(&priv->mutex);
+       ieee80211_remain_on_channel_expired(priv->hw);
+       iwlagn_disable_roc(priv);
+       mutex_unlock(&priv->mutex);
+}
+
+static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
+                                    struct ieee80211_channel *channel,
+                                    enum nl80211_channel_type channel_type,
+                                    int duration)
+{
+       struct iwl_priv *priv = hw->priv;
+       int err = 0;
+
+       if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+               return -EOPNOTSUPP;
+
+       if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes &
+                                       BIT(NL80211_IFTYPE_P2P_CLIENT)))
+               return -EOPNOTSUPP;
+
+       mutex_lock(&priv->mutex);
+
+       if (priv->contexts[IWL_RXON_CTX_PAN].is_active ||
+           test_bit(STATUS_SCAN_HW, &priv->status)) {
+               err = -EBUSY;
+               goto out;
+       }
+
+       priv->contexts[IWL_RXON_CTX_PAN].is_active = true;
+       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]);
+       queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work,
+                          msecs_to_jiffies(duration + 20));
+
+       msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */
+       ieee80211_ready_on_channel(priv->hw);
+
+ out:
+       mutex_unlock(&priv->mutex);
+
+       return err;
+}
+
+static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
+{
+       struct iwl_priv *priv = hw->priv;
+
+       if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+               return -EOPNOTSUPP;
+
+       cancel_delayed_work_sync(&priv->_agn.hw_roc_work);
+
+       mutex_lock(&priv->mutex);
+       iwlagn_disable_roc(priv);
+       mutex_unlock(&priv->mutex);
+
+       return 0;
+}
+
 /*****************************************************************************
  *
  * driver setup and teardown
@@ -3726,8 +3263,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
        INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
        INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
        INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
-       INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
-       INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
+       INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done);
 
        iwl_setup_scan_deferred_work(priv);
 
@@ -3742,19 +3278,12 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
        priv->ucode_trace.data = (unsigned long)priv;
        priv->ucode_trace.function = iwl_bg_ucode_trace;
 
-       if (priv->cfg->ops->lib->recover_from_tx_stall) {
-               init_timer(&priv->monitor_recover);
-               priv->monitor_recover.data = (unsigned long)priv;
-               priv->monitor_recover.function =
-                       priv->cfg->ops->lib->recover_from_tx_stall;
-       }
+       init_timer(&priv->watchdog);
+       priv->watchdog.data = (unsigned long)priv;
+       priv->watchdog.function = iwl_bg_watchdog;
 
-       if (!priv->cfg->base_params->use_isr_legacy)
-               tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-                       iwl_irq_tasklet, (unsigned long)priv);
-       else
-               tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-                       iwl_irq_tasklet_legacy, (unsigned long)priv);
+       tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+               iwl_irq_tasklet, (unsigned long)priv);
 }
 
 static void iwl_cancel_deferred_work(struct iwl_priv *priv)
@@ -3762,8 +3291,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
        if (priv->cfg->ops->lib->cancel_deferred_work)
                priv->cfg->ops->lib->cancel_deferred_work(priv);
 
-       cancel_delayed_work_sync(&priv->init_alive_start);
-       cancel_delayed_work(&priv->alive_start);
        cancel_work_sync(&priv->run_time_calib_work);
        cancel_work_sync(&priv->beacon_update);
 
@@ -3804,10 +3331,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
        spin_lock_init(&priv->sta_lock);
        spin_lock_init(&priv->hcmd_lock);
 
-       INIT_LIST_HEAD(&priv->free_frames);
-
        mutex_init(&priv->mutex);
-       mutex_init(&priv->sync_cmd_mutex);
 
        priv->ieee_channels = NULL;
        priv->ieee_rates = NULL;
@@ -3824,6 +3348,8 @@ static int iwl_init_drv(struct iwl_priv *priv)
        priv->force_reset[IWL_FW_RESET].reset_duration =
                IWL_DELAY_NEXT_FORCE_FW_RELOAD;
 
+       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,
@@ -3842,12 +3368,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
                priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF;
        }
 
-       /* Set the tx_power_user_lmt to the lowest power level
-        * this value will get overwritten by channel max power avg
-        * from eeprom */
-       priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN;
-       priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN;
-
        ret = iwl_init_channel_map(priv);
        if (ret) {
                IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
@@ -3877,7 +3397,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
        kfree(priv->scan_cmd);
 }
 
-#ifdef CONFIG_IWL5000
 struct ieee80211_ops iwlagn_hw_ops = {
        .tx = iwlagn_mac_tx,
        .start = iwlagn_mac_start,
@@ -3899,29 +3418,34 @@ struct ieee80211_ops iwlagn_hw_ops = {
        .channel_switch = iwlagn_mac_channel_switch,
        .flush = iwlagn_mac_flush,
        .tx_last_beacon = iwl_mac_tx_last_beacon,
+       .remain_on_channel = iwl_mac_remain_on_channel,
+       .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel,
+       .offchannel_tx = iwl_mac_offchannel_tx,
+       .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
+       CFG80211_TESTMODE_CMD(iwl_testmode_cmd)
 };
-#endif
 
-static void iwl_hw_detect(struct iwl_priv *priv)
+static u32 iwl_hw_detect(struct iwl_priv *priv)
 {
-       priv->hw_rev = _iwl_read32(priv, CSR_HW_REV);
-       priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG);
-       pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id);
-       IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
+       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);
 }
 
 static int iwl_set_hw_params(struct iwl_priv *priv)
 {
        priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
        priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
-       if (priv->cfg->mod_params->amsdu_size_8K)
+       if (iwlagn_mod_params.amsdu_size_8K)
                priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
        else
                priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
 
        priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
 
-       if (priv->cfg->mod_params->disable_11n)
+       if (iwlagn_mod_params.disable_11n)
                priv->cfg->sku &= ~IWL_SKU_N;
 
        /* Device-specific setup */
@@ -3950,6 +3474,28 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
        7, 6, 5, 4,
 };
 
+/* This function both allocates and initializes hw and priv. */
+static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
+{
+       struct iwl_priv *priv;
+       /* mac80211 allocates memory for this device instance, including
+        *   space for this driver's private structure */
+       struct ieee80211_hw *hw;
+
+       hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwlagn_hw_ops);
+       if (hw == NULL) {
+               pr_err("%s: Can not allocate network device\n",
+                      cfg->name);
+               goto out;
+       }
+
+       priv = hw->priv;
+       priv->hw = hw;
+
+out:
+       return hw;
+}
+
 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err = 0, i;
@@ -3958,24 +3504,12 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        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
         ************************/
 
-       /* Disabling hardware scan means that mac80211 will perform scans
-        * "the hard way", rather than using device's scan. */
-       if (cfg->mod_params->disable_hw_scan) {
-               dev_printk(KERN_DEBUG, &(pdev->dev),
-                       "sw scan support is deprecated\n");
-#ifdef CONFIG_IWL5000
-               iwlagn_hw_ops.hw_scan = NULL;
-#endif
-#ifdef CONFIG_IWL4965
-               iwl4965_hw_ops.hw_scan = NULL;
-#endif
-       }
-
        hw = iwl_alloc_all(cfg);
        if (!hw) {
                err = -ENOMEM;
@@ -3984,6 +3518,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        priv = hw->priv;
        /* At this point both hw and priv are allocated. */
 
+       priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED;
+
        /*
         * The default context is always valid,
         * more may be discovered when firmware
@@ -4026,6 +3562,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
        priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
                BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
+#ifdef CONFIG_IWL_P2P
+       priv->contexts[IWL_RXON_CTX_PAN].interface_modes |=
+               BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO);
+#endif
        priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
        priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
        priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
@@ -4044,8 +3584,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
                true : false;
 
-       /* enable/disable bt channel announcement */
+       /* enable/disable bt channel inhibition */
        priv->bt_ch_announce = iwlagn_bt_ch_announce;
+       IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n",
+                      (priv->bt_ch_announce) ? "On" : "Off");
 
        if (iwl_alloc_traffic_mem(priv))
                IWL_ERR(priv, "Not enough memory to generate traffic log\n");
@@ -4110,16 +3652,15 @@ 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);
 
-       iwl_hw_detect(priv);
+       hw_rev = iwl_hw_detect(priv);
        IWL_INFO(priv, "Detected %s, REV=0x%X\n",
-               priv->cfg->name, priv->hw_rev);
+               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);
 
-       iwl_prepare_card_hw(priv);
-       if (!priv->hw_ready) {
+       if (iwl_prepare_card_hw(priv)) {
                IWL_WARN(priv, "Failed, HW not ready\n");
                goto out_iounmap;
        }
@@ -4128,7 +3669,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * 4. Read EEPROM
         *****************/
        /* Read the EEPROM */
-       err = iwl_eeprom_init(priv);
+       err = iwl_eeprom_init(priv, hw_rev);
        if (err) {
                IWL_ERR(priv, "Unable to init EEPROM\n");
                goto out_iounmap;
@@ -4180,10 +3721,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        pci_enable_msi(priv->pci_dev);
 
-       if (priv->cfg->ops->lib->isr_ops.alloc)
-               priv->cfg->ops->lib->isr_ops.alloc(priv);
+       iwl_alloc_isr_ict(priv);
 
-       err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr,
+       err = request_irq(priv->pci_dev->irq, iwl_isr_ict,
                          IRQF_SHARED, DRV_NAME, priv);
        if (err) {
                IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
@@ -4192,19 +3732,20 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        iwl_setup_deferred_work(priv);
        iwl_setup_rx_handlers(priv);
+       iwl_testmode_init(priv);
 
        /*********************************************
         * 8. Enable interrupts and read RFKILL state
         *********************************************/
 
-       /* enable interrupts if needed: hw bug w/a */
+       /* 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_interrupts(priv);
+       iwl_enable_rfkill_int(priv);
 
        /* If platform's RF_KILL switch is NOT set to KILL */
        if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
@@ -4230,8 +3771,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
        free_irq(priv->pci_dev->irq, priv);
-       if (priv->cfg->ops->lib->isr_ops.free)
-               priv->cfg->ops->lib->isr_ops.free(priv);
+       iwl_free_isr_ict(priv);
  out_disable_msi:
        pci_disable_msi(priv->pci_dev);
        iwl_uninit_drv(priv);
@@ -4271,20 +3811,15 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
         * we need to set STATUS_EXIT_PENDING bit.
         */
        set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+       iwl_leds_exit(priv);
+
        if (priv->mac80211_registered) {
                ieee80211_unregister_hw(priv->hw);
                priv->mac80211_registered = 0;
-       } else {
-               iwl_down(priv);
        }
 
-       /*
-        * Make sure device is reset to low power before unloading driver.
-        * This may be redundant with iwl_down(), but there are paths to
-        * run iwl_down() without calling apm_ops.stop(), and there are
-        * paths to avoid running iwl_down() at all before leaving driver.
-        * This (inexpensive) call *makes sure* device is reset.
-        */
+       /* Reset to low power before unloading driver. */
        iwl_apm_stop(priv);
 
        iwl_tt_exit(priv);
@@ -4326,8 +3861,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 
        iwl_uninit_drv(priv);
 
-       if (priv->cfg->ops->lib->isr_ops.free)
-               priv->cfg->ops->lib->isr_ops.free(priv);
+       iwl_free_isr_ict(priv);
 
        dev_kfree_skb(priv->beacon_skb);
 
@@ -4343,12 +3877,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 
 /* Hardware specific file defines the PCI IDs table for that hardware module */
 static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
-#ifdef CONFIG_IWL4965
-       {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
-       {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
-#endif /* CONFIG_IWL4965 */
-#ifdef CONFIG_IWL5000
-/* 5100 Series WiFi */
        {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 */
@@ -4418,7 +3946,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
        {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
 
-/* 6x00 Series Gen2a */
+/* 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)},
@@ -4427,7 +3955,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
        {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
 
-/* 6x00 Series Gen2b */
+/* 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)},
@@ -4453,7 +3981,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
        {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
 
-/* 6x50 WiFi/WiMax Series Gen2 */
+/* 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)},
@@ -4491,7 +4019,48 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
        {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
 
-#endif /* CONFIG_IWL5000 */
+/* 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}
 };
@@ -4541,43 +4110,21 @@ module_exit(iwl_exit);
 module_init(iwl_init);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-module_param_named(debug50, iwl_debug_level, uint, S_IRUGO);
-MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)");
 module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "debug output mask");
 #endif
 
-module_param_named(swcrypto50, iwlagn_mod_params.sw_crypto, bool, S_IRUGO);
-MODULE_PARM_DESC(swcrypto50,
-                "using crypto in software (default 0 [hardware]) (deprecated)");
 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_num50,
-                  iwlagn_mod_params.num_of_queues, int, S_IRUGO);
-MODULE_PARM_DESC(queues_num50,
-                "number of hw queues in 50xx series (deprecated)");
 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_disable50, iwlagn_mod_params.disable_11n, int, S_IRUGO);
-MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality (deprecated)");
 module_param_named(11n_disable, iwlagn_mod_params.disable_11n, int, S_IRUGO);
 MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
-module_param_named(amsdu_size_8K50, iwlagn_mod_params.amsdu_size_8K,
-                  int, S_IRUGO);
-MODULE_PARM_DESC(amsdu_size_8K50,
-                "enable 8K amsdu size in 50XX series (deprecated)");
 module_param_named(amsdu_size_8K, iwlagn_mod_params.amsdu_size_8K,
                   int, S_IRUGO);
 MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
-module_param_named(fw_restart50, iwlagn_mod_params.restart_fw, int, S_IRUGO);
-MODULE_PARM_DESC(fw_restart50,
-                "restart firmware in case of error (deprecated)");
 module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO);
 MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
-module_param_named(
-       disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO);
-MODULE_PARM_DESC(disable_hw_scan,
-                "disable hardware scanning (default 0) (deprecated)");
 
 module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int,
                   S_IRUGO);
@@ -4588,6 +4135,12 @@ module_param_named(antenna_coupling, iwlagn_ant_coupling, int, S_IRUGO);
 MODULE_PARM_DESC(antenna_coupling,
                 "specify antenna coupling in dB (defualt: 0 dB)");
 
-module_param_named(bt_ch_announce, iwlagn_bt_ch_announce, bool, S_IRUGO);
-MODULE_PARM_DESC(bt_ch_announce,
-                "Enable BT channel announcement mode (default: enable)");
+module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO);
+MODULE_PARM_DESC(bt_ch_inhibition,
+                "Disable BT channel inhibition (default: enable)");
+
+module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO);
+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])");