Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-2.6.git] / drivers / net / wireless / iwlwifi / iwl-agn.c
index d5eeb3e..7e6c463 100644 (file)
@@ -32,9 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-/* TODO: remove include to PCI*.h when no PCI will be needed here */
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -59,7 +56,7 @@
 #include "iwl-agn-calib.h"
 #include "iwl-agn.h"
 #include "iwl-pci.h"
-
+#include "iwl-trans.h"
 
 /******************************************************************************
  *
@@ -93,12 +90,10 @@ void iwl_update_chain_flags(struct iwl_priv *priv)
 {
        struct iwl_rxon_context *ctx;
 
-       if (priv->cfg->ops->hcmd->set_rxon_chain) {
-               for_each_context(priv, ctx) {
-                       priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-                       if (ctx->active.rx_chain != ctx->staging.rx_chain)
-                               iwlagn_commit_rxon(priv, ctx);
-               }
+       for_each_context(priv, ctx) {
+               iwlagn_set_rxon_chain(priv, ctx);
+               if (ctx->active.rx_chain != ctx->staging.rx_chain)
+                       iwlagn_commit_rxon(priv, ctx);
        }
 }
 
@@ -135,6 +130,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
        struct iwl_host_cmd cmd = {
                .id = REPLY_TX_BEACON,
        };
+       struct ieee80211_tx_info *info;
        u32 frame_size;
        u32 rate_flags;
        u32 rate;
@@ -175,14 +171,31 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
                           frame_size);
 
        /* Set up packet rate and flags */
-       rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx);
+       info = IEEE80211_SKB_CB(priv->beacon_skb);
+
+       /*
+        * Let's set up the rate at least somewhat correctly;
+        * it will currently not actually be used by the uCode,
+        * it uses the broadcast station's rate instead.
+        */
+       if (info->control.rates[0].idx < 0 ||
+           info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
+               rate = 0;
+       else
+               rate = info->control.rates[0].idx;
+
        priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
                                              priv->hw_params.valid_tx_ant);
        rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
-       if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE))
+
+       /* In mac80211, rates for 5 GHz start at 0 */
+       if (info->band == IEEE80211_BAND_5GHZ)
+               rate += IWL_FIRST_OFDM_RATE;
+       else if (rate >= IWL_FIRST_CCK_RATE && rate <= IWL_LAST_CCK_RATE)
                rate_flags |= RATE_MCS_CCK_MSK;
-       tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate,
-                       rate_flags);
+
+       tx_beacon_cmd->tx.rate_n_flags =
+                       iwl_hw_set_rate_n_flags(rate, rate_flags);
 
        /* Submit command */
        cmd.len[0] = sizeof(*tx_beacon_cmd);
@@ -245,7 +258,7 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work)
        /* dont send host command if rf-kill is on */
        if (!iwl_is_ready_rf(priv))
                return;
-       priv->cfg->ops->hcmd->send_bt_config(priv);
+       iwlagn_send_advance_bt_config(priv);
 }
 
 static void iwl_bg_bt_full_concurrency(struct work_struct *work)
@@ -272,12 +285,11 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
         * to avoid 3-wire collisions
         */
        for_each_context(priv, ctx) {
-               if (priv->cfg->ops->hcmd->set_rxon_chain)
-                       priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+               iwlagn_set_rxon_chain(priv, ctx);
                iwlagn_commit_rxon(priv, ctx);
        }
 
-       priv->cfg->ops->hcmd->send_bt_config(priv);
+       iwlagn_send_advance_bt_config(priv);
 out:
        mutex_unlock(&priv->mutex);
 }
@@ -495,9 +507,9 @@ static void iwl_rx_handle(struct iwl_priv *priv)
 
                rxq->queue[i] = NULL;
 
-               pci_unmap_page(priv->pci_dev, rxb->page_dma,
+               dma_unmap_page(priv->bus.dev, rxb->page_dma,
                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                              PCI_DMA_FROMDEVICE);
+                              DMA_FROM_DEVICE);
                pkt = rxb_addr(rxb);
 
                len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
@@ -579,9 +591,9 @@ static void iwl_rx_handle(struct iwl_priv *priv)
                 * rx_free list for reuse later. */
                spin_lock_irqsave(&rxq->lock, flags);
                if (rxb->page != NULL) {
-                       rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
+                       rxb->page_dma = dma_map_page(priv->bus.dev, rxb->page,
                                0, PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
+                               DMA_FROM_DEVICE);
                        list_add_tail(&rxb->list, &rxq->rx_free);
                        rxq->free_count++;
                } else
@@ -937,22 +949,28 @@ static struct attribute_group iwl_attribute_group = {
  *
  ******************************************************************************/
 
-static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
+static void iwl_free_fw_desc(struct iwl_priv *priv, struct fw_desc *desc)
 {
        if (desc->v_addr)
-               dma_free_coherent(&pci_dev->dev, desc->len,
+               dma_free_coherent(priv->bus.dev, desc->len,
                                  desc->v_addr, desc->p_addr);
        desc->v_addr = NULL;
        desc->len = 0;
 }
 
-static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img)
+static void iwl_free_fw_img(struct iwl_priv *priv, struct fw_img *img)
+{
+       iwl_free_fw_desc(priv, &img->code);
+       iwl_free_fw_desc(priv, &img->data);
+}
+
+static void iwl_dealloc_ucode(struct iwl_priv *priv)
 {
-       iwl_free_fw_desc(pci_dev, &img->code);
-       iwl_free_fw_desc(pci_dev, &img->data);
+       iwl_free_fw_img(priv, &priv->ucode_rt);
+       iwl_free_fw_img(priv, &priv->ucode_init);
 }
 
-static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
+static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc,
                             const void *data, size_t len)
 {
        if (!len) {
@@ -960,21 +978,16 @@ static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
                return -EINVAL;
        }
 
-       desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len,
+       desc->v_addr = dma_alloc_coherent(priv->bus.dev, len,
                                          &desc->p_addr, GFP_KERNEL);
        if (!desc->v_addr)
                return -ENOMEM;
+
        desc->len = len;
        memcpy(desc->v_addr, data, len);
        return 0;
 }
 
-static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
-{
-       iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt);
-       iwl_free_fw_img(priv->pci_dev, &priv->ucode_init);
-}
-
 struct iwlagn_ucode_capabilities {
        u32 max_probe_length;
        u32 standard_phy_calibration_size;
@@ -1019,8 +1032,8 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
                       priv->firmware_name);
 
        return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
-                                      &priv->pci_dev->dev, GFP_KERNEL, priv,
-                                      iwl_ucode_callback);
+                                      priv->bus.dev,
+                                      GFP_KERNEL, priv, iwl_ucode_callback);
 }
 
 struct iwlagn_firmware_pieces {
@@ -1441,19 +1454,19 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        /* Runtime instructions and 2 copies of data:
         * 1) unmodified from disk
         * 2) backup cache for save/restore during power-downs */
-       if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code,
+       if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.code,
                              pieces.inst, pieces.inst_size))
                goto err_pci_alloc;
-       if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data,
+       if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.data,
                              pieces.data, pieces.data_size))
                goto err_pci_alloc;
 
        /* Initialization instructions and data */
        if (pieces.init_size && pieces.init_data_size) {
-               if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code,
+               if (iwl_alloc_fw_desc(priv, &priv->ucode_init.code,
                                      pieces.init, pieces.init_size))
                        goto err_pci_alloc;
-               if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data,
+               if (iwl_alloc_fw_desc(priv, &priv->ucode_init.data,
                                      pieces.init_data, pieces.init_data_size))
                        goto err_pci_alloc;
        }
@@ -1522,7 +1535,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        if (err)
                IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
-       err = sysfs_create_group(&priv->pci_dev->dev.kobj,
+       err = sysfs_create_group(&(priv->bus.dev->kobj),
                                        &iwl_attribute_group);
        if (err) {
                IWL_ERR(priv, "failed to create sysfs device attributes\n");
@@ -1543,10 +1556,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 
  err_pci_alloc:
        IWL_ERR(priv, "failed to allocate pci memory\n");
-       iwl_dealloc_ucode_pci(priv);
+       iwl_dealloc_ucode(priv);
  out_unbind:
        complete(&priv->_agn.firmware_loading_complete);
-       device_release_driver(&priv->pci_dev->dev);
+       device_release_driver(priv->bus.dev);
        release_firmware(ucode_raw);
 }
 
@@ -2001,7 +2014,7 @@ int iwl_alive_start(struct iwl_priv *priv)
                priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
                priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
                priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
-               priv->cfg->ops->hcmd->send_bt_config(priv);
+               iwlagn_send_advance_bt_config(priv);
                priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
                iwlagn_send_prio_tbl(priv);
 
@@ -2014,7 +2027,13 @@ int iwl_alive_start(struct iwl_priv *priv)
                                         BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
                if (ret)
                        return ret;
+       } else {
+               /*
+                * default is 2-wire BT coexexistence support
+                */
+               iwl_send_bt_config(priv);
        }
+
        if (priv->hw_params.calib_rt_cfg)
                iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
 
@@ -2023,8 +2042,7 @@ int iwl_alive_start(struct iwl_priv *priv)
        priv->active_rate = IWL_RATES_MASK;
 
        /* Configure Tx antenna selection based on H/W config */
-       if (priv->cfg->ops->hcmd->set_tx_ant)
-               priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant);
+       iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant);
 
        if (iwl_is_associated_ctx(ctx)) {
                struct iwl_rxon_cmd *active_rxon =
@@ -2038,16 +2056,7 @@ int iwl_alive_start(struct iwl_priv *priv)
                for_each_context(priv, tmp)
                        iwl_connection_init_rx_config(priv, tmp);
 
-               if (priv->cfg->ops->hcmd->set_rxon_chain)
-                       priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-       }
-
-       if (!priv->cfg->bt_params || (priv->cfg->bt_params &&
-           !priv->cfg->bt_params->advanced_bt_coexist)) {
-               /*
-                * default is 2-wire BT coexexistence support
-                */
-               priv->cfg->ops->hcmd->send_bt_config(priv);
+               iwlagn_set_rxon_chain(priv, ctx);
        }
 
        iwl_reset_run_time_calib(priv);
@@ -2547,11 +2556,10 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
                            WIPHY_FLAG_DISABLE_BEACON_HINTS |
                            WIPHY_FLAG_IBSS_RSN;
 
-       /*
-        * For now, disable PS by default because it affects
-        * RX performance significantly.
-        */
-       hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+       if (iwlagn_mod_params.power_save)
+               hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+       else
+               hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
        hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
        /* we create the 802.11 header and a zero-length SSID element */
@@ -3273,9 +3281,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
        priv->rx_statistics_jiffies = jiffies;
 
        /* Choose which receivers/antennas to use */
-       if (priv->cfg->ops->hcmd->set_rxon_chain)
-               priv->cfg->ops->hcmd->set_rxon_chain(priv,
-                                       &priv->contexts[IWL_RXON_CTX_BSS]);
+       iwlagn_set_rxon_chain(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
 
        iwl_init_scan_params(priv);
 
@@ -3351,10 +3357,6 @@ struct ieee80211_ops iwlagn_hw_ops = {
 
 static u32 iwl_hw_detect(struct iwl_priv *priv)
 {
-       u8 rev_id;
-
-       pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
-       IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
        return iwl_read32(priv, CSR_HW_REV);
 }
 
@@ -3479,30 +3481,41 @@ static void iwl_init_context(struct iwl_priv *priv)
        BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
 }
 
-int iwl_probe(struct pci_dev *pdev, struct iwl_cfg *cfg)
+int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
+               struct iwl_cfg *cfg)
 {
        int err = 0;
        struct iwl_priv *priv;
        struct ieee80211_hw *hw;
-       u16 pci_cmd, num_mac;
+       u16 num_mac;
        u32 hw_rev;
 
        /************************
         * 1. Allocating HW data
         ************************/
-
        hw = iwl_alloc_all(cfg);
        if (!hw) {
                err = -ENOMEM;
-               goto out;       }
+               goto out;
+       }
+
        priv = hw->priv;
+
+       priv->bus.priv = priv;
+       priv->bus.bus_specific = bus_specific;
+       priv->bus.ops = bus_ops;
+       priv->bus.irq = priv->bus.ops->get_irq(&priv->bus);
+       priv->bus.ops->set_drv_data(&priv->bus, priv);
+       priv->bus.dev = priv->bus.ops->get_dev(&priv->bus);
+
+       iwl_trans_register(&priv->trans);
+
        /* At this point both hw and priv are allocated. */
 
-       SET_IEEE80211_DEV(hw, &pdev->dev);
+       SET_IEEE80211_DEV(hw, priv->bus.dev);
 
        IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
        priv->cfg = cfg;
-       priv->pci_dev = pdev;
        priv->inta_mask = CSR_INI_SET_MASK;
 
        /* is antenna coupling more than 35dB ? */
@@ -3518,52 +3531,6 @@ int iwl_probe(struct pci_dev *pdev, struct iwl_cfg *cfg)
        if (iwl_alloc_traffic_mem(priv))
                IWL_ERR(priv, "Not enough memory to generate traffic log\n");
 
-       /**************************
-        * 2. Initializing PCI bus
-        **************************/
-       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-                               PCIE_LINK_STATE_CLKPM);
-
-       if (pci_enable_device(pdev)) {
-               err = -ENODEV;
-               goto out_ieee80211_free_hw;
-       }
-
-       pci_set_master(pdev);
-
-       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
-       if (!err)
-               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
-       if (err) {
-               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-               if (!err)
-                       err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-               /* both attempts failed: */
-               if (err) {
-                       IWL_WARN(priv, "No suitable DMA available.\n");
-                       goto out_pci_disable_device;
-               }
-       }
-
-       err = pci_request_regions(pdev, DRV_NAME);
-       if (err)
-               goto out_pci_disable_device;
-
-       pci_set_drvdata(pdev, priv);
-
-
-       /***********************
-        * 3. Read REV register
-        ***********************/
-       priv->hw_base = pci_iomap(pdev, 0, 0);
-       if (!priv->hw_base) {
-               err = -ENODEV;
-               goto out_pci_release_regions;
-       }
-
-       IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
-               (unsigned long long) pci_resource_len(pdev, 0));
-       IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
 
        /* these spin locks will be used in apm_ops.init and EEPROM access
         * we should init now
@@ -3578,17 +3545,17 @@ int iwl_probe(struct pci_dev *pdev, struct iwl_cfg *cfg)
         */
        iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 
+       /***********************
+        * 3. Read REV register
+        ***********************/
        hw_rev = iwl_hw_detect(priv);
        IWL_INFO(priv, "Detected %s, REV=0x%X\n",
                priv->cfg->name, hw_rev);
 
-       /* We disable the RETRY_TIMEOUT register (0x41) to keep
-        * PCI Tx retries from interfering with C3 CPU state */
-       pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
-
        if (iwl_prepare_card_hw(priv)) {
+               err = -EIO;
                IWL_WARN(priv, "Failed, HW not ready\n");
-               goto out_iounmap;
+               goto out_free_traffic_mem;
        }
 
        /*****************
@@ -3598,7 +3565,7 @@ int iwl_probe(struct pci_dev *pdev, struct iwl_cfg *cfg)
        err = iwl_eeprom_init(priv, hw_rev);
        if (err) {
                IWL_ERR(priv, "Unable to init EEPROM\n");
-               goto out_iounmap;
+               goto out_free_traffic_mem;
        }
        err = iwl_eeprom_check_version(priv);
        if (err)
@@ -3628,6 +3595,7 @@ int iwl_probe(struct pci_dev *pdev, struct iwl_cfg *cfg)
         * 5. Setup HW constants
         ************************/
        if (iwl_set_hw_params(priv)) {
+               err = -ENOENT;
                IWL_ERR(priv, "failed to set hw parameters\n");
                goto out_free_eeprom;
        }
@@ -3644,15 +3612,13 @@ int iwl_probe(struct pci_dev *pdev, struct iwl_cfg *cfg)
        /********************
         * 7. Setup services
         ********************/
-       pci_enable_msi(priv->pci_dev);
-
        iwl_alloc_isr_ict(priv);
 
-       err = request_irq(priv->pci_dev->irq, iwl_isr_ict,
-                         IRQF_SHARED, DRV_NAME, priv);
+       err = request_irq(priv->bus.irq, iwl_isr_ict, IRQF_SHARED,
+                         DRV_NAME, priv);
        if (err) {
-               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
-               goto out_disable_msi;
+               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq);
+               goto out_uninit_drv;
        }
 
        iwl_setup_deferred_work(priv);
@@ -3660,16 +3626,9 @@ int iwl_probe(struct pci_dev *pdev, struct iwl_cfg *cfg)
        iwl_testmode_init(priv);
 
        /*********************************************
-        * 8. Enable interrupts and read RFKILL state
+        * 8. Enable interrupts
         *********************************************/
 
-       /* enable rfkill interrupt: hw bug w/a */
-       pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
-       if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
-               pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
-               pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
-       }
-
        iwl_enable_rfkill_int(priv);
 
        /* If platform's RF_KILL switch is NOT set to KILL */
@@ -3695,41 +3654,30 @@ int iwl_probe(struct pci_dev *pdev, struct iwl_cfg *cfg)
  out_destroy_workqueue:
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
-       free_irq(priv->pci_dev->irq, priv);
- out_disable_msi:
+       free_irq(priv->bus.irq, priv);
        iwl_free_isr_ict(priv);
-       pci_disable_msi(priv->pci_dev);
+ out_uninit_drv:
        iwl_uninit_drv(priv);
  out_free_eeprom:
        iwl_eeprom_free(priv);
- out_iounmap:
-       pci_iounmap(pdev, priv->hw_base);
- out_pci_release_regions:
-       pci_set_drvdata(pdev, NULL);
-       pci_release_regions(pdev);
- out_pci_disable_device:
-       pci_disable_device(pdev);
- out_ieee80211_free_hw:
+ out_free_traffic_mem:
        iwl_free_traffic_mem(priv);
        ieee80211_free_hw(priv->hw);
  out:
        return err;
 }
 
-void __devexit iwl_remove(struct pci_dev *pdev)
+void __devexit iwl_remove(struct iwl_priv * priv)
 {
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
        unsigned long flags;
 
-       if (!priv)
-               return;
-
        wait_for_completion(&priv->_agn.firmware_loading_complete);
 
        IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
        iwl_dbgfs_unregister(priv);
-       sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+       sysfs_remove_group(&priv->bus.dev->kobj,
+                          &iwl_attribute_group);
 
        /* ieee80211_unregister_hw call wil cause iwl_mac_stop to
         * to be called and iwl_down since we are removing the device
@@ -3759,10 +3707,9 @@ void __devexit iwl_remove(struct pci_dev *pdev)
 
        iwl_synchronize_irq(priv);
 
-       iwl_dealloc_ucode_pci(priv);
+       iwl_dealloc_ucode(priv);
 
-       if (priv->rxq.bd)
-               iwlagn_rx_queue_free(priv, &priv->rxq);
+       priv->trans.ops->rx_free(priv);
        iwlagn_hw_txq_ctx_free(priv);
 
        iwl_eeprom_free(priv);
@@ -3778,12 +3725,8 @@ void __devexit iwl_remove(struct pci_dev *pdev)
        priv->workqueue = NULL;
        iwl_free_traffic_mem(priv);
 
-       free_irq(priv->pci_dev->irq, priv);
-       pci_disable_msi(priv->pci_dev);
-       pci_iounmap(pdev, priv->hw_base);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
+       free_irq(priv->bus.irq, priv);
+       priv->bus.ops->set_drv_data(&priv->bus, NULL);
 
        iwl_uninit_drv(priv);
 
@@ -3869,6 +3812,10 @@ MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
 module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);
 MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");
 
+module_param_named(wd_disable, iwlagn_mod_params.wd_disable, bool, S_IRUGO);
+MODULE_PARM_DESC(wd_disable,
+               "Disable stuck queue watchdog timer (default: 0 [enabled])");
+
 /*
  * set bt_coex_active to true, uCode will do kill/defer
  * every time the priority line is asserted (BT is sending signals on the
@@ -3893,6 +3840,16 @@ module_param_named(led_mode, iwlagn_mod_params.led_mode, int, S_IRUGO);
 MODULE_PARM_DESC(led_mode, "0=system default, "
                "1=On(RF On)/Off(RF Off), 2=blinking (default: 0)");
 
+module_param_named(power_save, iwlagn_mod_params.power_save,
+               bool, S_IRUGO);
+MODULE_PARM_DESC(power_save,
+                "enable WiFi power management (default: disable)");
+
+module_param_named(power_level, iwlagn_mod_params.power_level,
+               int, S_IRUGO);
+MODULE_PARM_DESC(power_level,
+                "default power save level (range from 1 - 5, default: 1)");
+
 /*
  * For now, keep using power level 1 instead of automatically
  * adjusting ...