iwlagn: enable only rfkill interrupt when device is down
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-agn.c
index 646864a..e0ec40e 100644 (file)
@@ -57,7 +57,7 @@
 #include "iwl-io.h"
 #include "iwl-helpers.h"
 #include "iwl-sta.h"
-#include "iwl-calib.h"
+#include "iwl-agn-calib.h"
 #include "iwl-agn.h"
 
 
@@ -91,14 +91,14 @@ static int iwlagn_ant_coupling;
 static bool iwlagn_bt_ch_announce = 1;
 
 /**
- * iwl_commit_rxon - commit staging_rxon to hardware
+ * iwlagn_commit_rxon - commit staging_rxon to hardware
  *
  * The RXON command in staging_rxon is committed to the hardware and
  * the active_rxon structure is updated with the new data.  This
  * function correctly transitions out of the RXON_ASSOC_MSK state if
  * a HW tune is required based on the RXON structure changes.
  */
-int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
        /* cast away the const for active_rxon in this function */
        struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
@@ -314,24 +314,26 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
 }
 
 static u32 iwl_fill_beacon_frame(struct iwl_priv *priv,
-                                         struct ieee80211_hdr *hdr,
-                                         int left)
+                                struct ieee80211_hdr *hdr,
+                                int left)
 {
-       if (!priv->ibss_beacon)
+       lockdep_assert_held(&priv->mutex);
+
+       if (!priv->beacon_skb)
                return 0;
 
-       if (priv->ibss_beacon->len > left)
+       if (priv->beacon_skb->len > left)
                return 0;
 
-       memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
+       memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
 
-       return priv->ibss_beacon->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,
-               u8 *beacon, u32 frame_size)
+                              struct iwl_tx_beacon_cmd *tx_beacon_cmd,
+                              u8 *beacon, u32 frame_size)
 {
        u16 tim_idx;
        struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
@@ -383,6 +385,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
                                sizeof(frame->u) - sizeof(*tx_beacon_cmd));
        if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
                return 0;
+       if (!frame_size)
+               return 0;
 
        /* Set up TX command fields */
        tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
@@ -393,7 +397,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
 
        /* Set up TX beacon command fields */
        iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame,
-                       frame_size);
+                          frame_size);
 
        /* Set up packet rate and flags */
        rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx);
@@ -648,15 +652,14 @@ static void iwl_bg_beacon_update(struct work_struct *work)
        /* Pull updated AP beacon from mac80211. will fail if not in AP mode */
        beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif);
        if (!beacon) {
-               IWL_ERR(priv, "update beacon failed\n");
+               IWL_ERR(priv, "update beacon failed -- keeping old\n");
                goto out;
        }
 
        /* new beacon skb is allocated every time; dispose previous.*/
-       if (priv->ibss_beacon)
-               dev_kfree_skb(priv->ibss_beacon);
+       dev_kfree_skb(priv->beacon_skb);
 
-       priv->ibss_beacon = beacon;
+       priv->beacon_skb = beacon;
 
        iwl_send_beacon_cmd(priv);
  out:
@@ -935,22 +938,6 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
                wake_up_interruptible(&priv->wait_command_queue);
 }
 
-int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
-{
-       if (src == IWL_PWR_SRC_VAUX) {
-               if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
-                       iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-                                              APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
-                                              ~APMG_PS_CTRL_MSK_PWR_SRC);
-       } else {
-               iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-                                      APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
-                                      ~APMG_PS_CTRL_MSK_PWR_SRC);
-       }
-
-       return 0;
-}
-
 static void iwl_bg_tx_flush(struct work_struct *work)
 {
        struct iwl_priv *priv =
@@ -2078,7 +2065,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        struct iwlagn_ucode_capabilities ucode_capa = {
                .max_probe_length = 200,
                .standard_phy_calibration_size =
-                       IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE,
+                       IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE,
        };
 
        memset(&pieces, 0, sizeof(pieces));
@@ -2120,18 +2107,23 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
         * firmware filename ... but we don't check for that and only rely
         * on the API version read from firmware header from here on forward
         */
-       if (api_ver < api_min || api_ver > api_max) {
-               IWL_ERR(priv, "Driver unable to support your firmware API. "
-                         "Driver supports v%u, firmware is v%u.\n",
-                         api_max, api_ver);
-               goto try_again;
-       }
+       /* no api version check required for experimental uCode */
+       if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) {
+               if (api_ver < api_min || api_ver > api_max) {
+                       IWL_ERR(priv,
+                               "Driver unable to support your firmware API. "
+                               "Driver supports v%u, firmware is v%u.\n",
+                               api_max, api_ver);
+                       goto try_again;
+               }
 
-       if (api_ver != api_max)
-               IWL_ERR(priv, "Firmware has old API version. Expected v%u, "
-                         "got v%u. New firmware can be obtained "
-                         "from http://www.intellinuxwireless.org.\n",
-                         api_max, api_ver);
+               if (api_ver != api_max)
+                       IWL_ERR(priv,
+                               "Firmware has old API version. Expected v%u, "
+                               "got v%u. New firmware can be obtained "
+                               "from http://www.intellinuxwireless.org.\n",
+                               api_max, api_ver);
+       }
 
        if (build)
                sprintf(buildstr, " build %u%s", build,
@@ -2256,13 +2248,15 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        if (pieces.init_evtlog_size)
                priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
        else
-               priv->_agn.init_evtlog_size = priv->cfg->max_event_log_size;
+               priv->_agn.init_evtlog_size =
+                       priv->cfg->base_params->max_event_log_size;
        priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr;
        priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr;
        if (pieces.inst_evtlog_size)
                priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
        else
-               priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size;
+               priv->_agn.inst_evtlog_size =
+                       priv->cfg->base_params->max_event_log_size;
        priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr;
 
        if (ucode_capa.pan) {
@@ -2732,7 +2726,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
        spin_unlock_irqrestore(&priv->lock, flags);
        priv->thermal_throttle.ct_kill_toggle = false;
 
-       if (priv->cfg->support_ct_kill_exit) {
+       if (priv->cfg->base_params->support_ct_kill_exit) {
                adv_cmd.critical_temperature_enter =
                        cpu_to_le32(priv->hw_params.ct_kill_threshold);
                adv_cmd.critical_temperature_exit =
@@ -2765,6 +2759,23 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
        }
 }
 
+static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
+{
+       struct iwl_calib_cfg_cmd calib_cfg_cmd;
+       struct iwl_host_cmd cmd = {
+               .id = CALIBRATION_CFG_CMD,
+               .len = sizeof(struct iwl_calib_cfg_cmd),
+               .data = &calib_cfg_cmd,
+       };
+
+       memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
+       calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
+       calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
+
+       return iwl_send_cmd(priv, &cmd);
+}
+
+
 /**
  * iwl_alive_start - called after REPLY_ALIVE notification received
  *                   from protocol/runtime uCode (initialization uCode's
@@ -2801,6 +2812,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
                goto restart;
        }
 
+
        /* After the ALIVE response, we can send host commands to the uCode */
        set_bit(STATUS_ALIVE, &priv->status);
 
@@ -2808,21 +2820,23 @@ static void iwl_alive_start(struct iwl_priv *priv)
                /* Enable timer to monitor the driver queues */
                mod_timer(&priv->monitor_recover,
                        jiffies +
-                       msecs_to_jiffies(priv->cfg->monitor_recover_period));
+                       msecs_to_jiffies(
+                         priv->cfg->base_params->monitor_recover_period));
        }
 
        if (iwl_is_rfkill(priv))
                return;
 
-       if (priv->cfg->advanced_bt_coexist) {
+       /* download priority table before any calibration request */
+       if (priv->cfg->bt_params &&
+           priv->cfg->bt_params->advanced_bt_coexist) {
                /* Configure Bluetooth device coexistence support */
                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);
                priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
-               if (bt_coex_active && priv->iw_mode != NL80211_IFTYPE_ADHOC)
-                       iwlagn_send_prio_tbl(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,
@@ -2830,6 +2844,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
                iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
                        BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
        }
+       if (priv->hw_params.calib_rt_cfg)
+               iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
+
        ieee80211_wake_queues(priv->hw);
 
        priv->active_rate = IWL_RATES_MASK;
@@ -2854,7 +2871,8 @@ static void iwl_alive_start(struct iwl_priv *priv)
                        priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
        }
 
-       if (!priv->cfg->advanced_bt_coexist) {
+       if (priv->cfg->bt_params &&
+           !priv->cfg->bt_params->advanced_bt_coexist) {
                /* Configure Bluetooth device coexistence support */
                priv->cfg->ops->hcmd->send_bt_config(priv);
        }
@@ -2907,7 +2925,11 @@ static void __iwl_down(struct iwl_priv *priv)
 
        /* reset BT coex data */
        priv->bt_status = 0;
-       priv->bt_traffic_load = priv->cfg->bt_init_traffic_load;
+       if (priv->cfg->bt_params)
+               priv->bt_traffic_load =
+                        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;
@@ -2969,14 +2991,13 @@ static void __iwl_down(struct iwl_priv *priv)
        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 */
-       priv->cfg->ops->lib->apm_ops.stop(priv);
+       iwl_apm_stop(priv);
 
  exit:
        memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
 
-       if (priv->ibss_beacon)
-               dev_kfree_skb(priv->ibss_beacon);
-       priv->ibss_beacon = NULL;
+       dev_kfree_skb(priv->beacon_skb);
+       priv->beacon_skb = NULL;
 
        /* clear out any free frames */
        iwl_clear_free_frames(priv);
@@ -3059,7 +3080,7 @@ static int __iwl_up(struct iwl_priv *priv)
        }
 
        for_each_context(priv, ctx) {
-               ret = iwl_alloc_bcast_station(priv, ctx, true);
+               ret = iwlagn_alloc_bcast_station(priv, ctx);
                if (ret) {
                        iwl_dealloc_bcast_stations(priv);
                        return ret;
@@ -3201,7 +3222,8 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
        }
 
        if (priv->start_calib) {
-               if (priv->cfg->bt_statistics) {
+               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,
@@ -3400,7 +3422,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
                    IEEE80211_HW_NEED_DTIM_PERIOD |
                    IEEE80211_HW_SPECTRUM_MGMT;
 
-       if (!priv->cfg->broken_powersave)
+       if (!priv->cfg->base_params->broken_powersave)
                hw->flags |= IEEE80211_HW_SUPPORTS_PS |
                             IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
@@ -3508,9 +3530,10 @@ static void iwl_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");
 }
@@ -3725,7 +3748,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
                }
                if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                        ret = 0;
-               if (priv->cfg->use_rts_for_aggregation) {
+               if (priv->cfg->ht_params &&
+                   priv->cfg->ht_params->use_rts_for_aggregation) {
                        struct iwl_station_priv *sta_priv =
                                (void *) sta->drv_priv;
                        /*
@@ -3739,7 +3763,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
                }
                break;
        case IEEE80211_AMPDU_TX_OPERATIONAL:
-               if (priv->cfg->use_rts_for_aggregation) {
+               if (priv->cfg->ht_params &&
+                   priv->cfg->ht_params->use_rts_for_aggregation) {
                        struct iwl_station_priv *sta_priv =
                                (void *) sta->drv_priv;
 
@@ -4057,7 +4082,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
                        priv->cfg->ops->lib->recover_from_tx_stall;
        }
 
-       if (!priv->cfg->use_isr_legacy)
+       if (!priv->cfg->base_params->use_isr_legacy)
                tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
                        iwl_irq_tasklet, (unsigned long)priv);
        else
@@ -4109,8 +4134,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
 {
        int ret;
 
-       priv->ibss_beacon = NULL;
-
        spin_lock_init(&priv->sta_lock);
        spin_lock_init(&priv->hcmd_lock);
 
@@ -4142,7 +4165,8 @@ static int iwl_init_drv(struct iwl_priv *priv)
        iwl_init_scan_params(priv);
 
        /* init bt coex */
-       if (priv->cfg->advanced_bt_coexist) {
+       if (priv->cfg->bt_params &&
+           priv->cfg->bt_params->advanced_bt_coexist) {
                priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
                priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
                priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
@@ -4273,9 +4297,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* 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) {
-               if (iwl_debug_level & IWL_DL_INFO)
-                       dev_printk(KERN_DEBUG, &(pdev->dev),
-                                  "Disabling hw_scan\n");
+               dev_printk(KERN_DEBUG, &(pdev->dev),
+                       "sw scan support is deprecated\n");
                iwl_hw_ops.hw_scan = NULL;
        }
 
@@ -4493,14 +4516,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * 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)
@@ -4580,7 +4603,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
         * paths to avoid running iwl_down() at all before leaving driver.
         * This (inexpensive) call *makes sure* device is reset.
         */
-       priv->cfg->ops->lib->apm_ops.stop(priv);
+       iwl_apm_stop(priv);
 
        iwl_tt_exit(priv);
 
@@ -4623,8 +4646,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 
        iwl_free_isr_ict(priv);
 
-       if (priv->ibss_beacon)
-               dev_kfree_skb(priv->ibss_beacon);
+       dev_kfree_skb(priv->beacon_skb);
 
        ieee80211_free_hw(priv->hw);
 }
@@ -4788,6 +4810,22 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
        {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
        {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
+
+/* 100 Series WiFi */
+       {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
+       {IWL_PCI_DEVICE(0x08AE, 0x1017, iwl100_bg_cfg)},
+
+/* 130 Series WiFi */
+       {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
+
 #endif /* CONFIG_IWL5000 */
 
        {0}
@@ -4876,7 +4914,8 @@ 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)");
+MODULE_PARM_DESC(disable_hw_scan,
+                "disable hardware scanning (default 0) (deprecated)");
 
 module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int,
                   S_IRUGO);