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 e2b319f..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);
 }
@@ -2002,7 +2014,7 @@ int iwl_alive_start(struct iwl_priv *priv)
                priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
                priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
                priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
-               priv->cfg->ops->hcmd->send_bt_config(priv);
+               iwlagn_send_advance_bt_config(priv);
                priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
                iwlagn_send_prio_tbl(priv);
 
@@ -2015,7 +2027,13 @@ int iwl_alive_start(struct iwl_priv *priv)
                                         BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
                if (ret)
                        return ret;
+       } else {
+               /*
+                * default is 2-wire BT coexexistence support
+                */
+               iwl_send_bt_config(priv);
        }
+
        if (priv->hw_params.calib_rt_cfg)
                iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
 
@@ -2024,8 +2042,7 @@ int iwl_alive_start(struct iwl_priv *priv)
        priv->active_rate = IWL_RATES_MASK;
 
        /* Configure Tx antenna selection based on H/W config */
-       if (priv->cfg->ops->hcmd->set_tx_ant)
-               priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant);
+       iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant);
 
        if (iwl_is_associated_ctx(ctx)) {
                struct iwl_rxon_cmd *active_rxon =
@@ -2039,16 +2056,7 @@ int iwl_alive_start(struct iwl_priv *priv)
                for_each_context(priv, tmp)
                        iwl_connection_init_rx_config(priv, tmp);
 
-               if (priv->cfg->ops->hcmd->set_rxon_chain)
-                       priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-       }
-
-       if (!priv->cfg->bt_params || (priv->cfg->bt_params &&
-           !priv->cfg->bt_params->advanced_bt_coexist)) {
-               /*
-                * default is 2-wire BT coexexistence support
-                */
-               priv->cfg->ops->hcmd->send_bt_config(priv);
+               iwlagn_set_rxon_chain(priv, ctx);
        }
 
        iwl_reset_run_time_calib(priv);
@@ -2548,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 */
@@ -3274,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);
 
@@ -3488,31 +3493,29 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
        /************************
         * 1. Allocating HW data
         ************************/
-       /* TODO: remove this nasty hack when PCI encapsulation is done
-        * assumes that struct pci_dev * is at the very beginning of whatever
-        * is pointed by bus_specific */
-       unsigned long *ppdev = bus_specific;
-       struct pci_dev *pdev = (struct pci_dev *) *ppdev;
-
        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, 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 ? */
@@ -3550,6 +3553,7 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
                priv->cfg->name, hw_rev);
 
        if (iwl_prepare_card_hw(priv)) {
+               err = -EIO;
                IWL_WARN(priv, "Failed, HW not ready\n");
                goto out_free_traffic_mem;
        }
@@ -3610,11 +3614,10 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
         ********************/
        iwl_alloc_isr_ict(priv);
 
-       err = request_irq(priv->bus.ops->get_irq(&priv->bus), 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->bus.ops->get_irq(&priv->bus));
+               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq);
                goto out_uninit_drv;
        }
 
@@ -3651,7 +3654,7 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
  out_destroy_workqueue:
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
-       free_irq(priv->bus.ops->get_irq(&priv->bus), priv);
+       free_irq(priv->bus.irq, priv);
        iwl_free_isr_ict(priv);
  out_uninit_drv:
        iwl_uninit_drv(priv);
@@ -3706,8 +3709,7 @@ void __devexit iwl_remove(struct iwl_priv * 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);
@@ -3723,7 +3725,7 @@ void __devexit iwl_remove(struct iwl_priv * priv)
        priv->workqueue = NULL;
        iwl_free_traffic_mem(priv);
 
-       free_irq(priv->bus.ops->get_irq(&priv->bus), priv);
+       free_irq(priv->bus.irq, priv);
        priv->bus.ops->set_drv_data(&priv->bus, NULL);
 
        iwl_uninit_drv(priv);
@@ -3810,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
@@ -3834,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 ...