iwlagn: move sync_irq to transport layer
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-agn.c
index 77ceb8d..c91e010 100644 (file)
@@ -56,7 +56,7 @@
 #include "iwl-agn-calib.h"
 #include "iwl-agn.h"
 #include "iwl-pci.h"
-
+#include "iwl-trans.h"
 
 /******************************************************************************
  *
@@ -90,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);
        }
 }
 
@@ -131,7 +129,9 @@ 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_SYNC,
        };
+       struct ieee80211_tx_info *info;
        u32 frame_size;
        u32 rate_flags;
        u32 rate;
@@ -172,14 +172,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);
@@ -189,7 +206,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
        cmd.data[1] = priv->beacon_skb->data;
        cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
 
-       return iwl_send_cmd_sync(priv, &cmd);
+       return trans_send_cmd(priv, &cmd);
 }
 
 static void iwl_bg_beacon_update(struct work_struct *work)
@@ -242,7 +259,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)
@@ -269,12 +286,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);
 }
@@ -563,7 +579,8 @@ static void iwl_rx_handle(struct iwl_priv *priv)
 
                if (reclaim) {
                        /* Invoke any callbacks, transfer the buffer to caller,
-                        * and fire off the (possibly) blocking iwl_send_cmd()
+                        * and fire off the (possibly) blocking
+                        * trans_send_cmd()
                         * as we reclaim the driver command queue */
                        if (rxb->page)
                                iwl_tx_cmd_complete(priv, rxb);
@@ -608,7 +625,7 @@ static void iwl_rx_handle(struct iwl_priv *priv)
 }
 
 /* tasklet for iwlagn interrupt */
-static void iwl_irq_tasklet(struct iwl_priv *priv)
+void iwl_irq_tasklet(struct iwl_priv *priv)
 {
        u32 inta = 0;
        u32 handled = 0;
@@ -1548,7 +1565,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        release_firmware(ucode_raw);
 }
 
-static const char *desc_lookup_text[] = {
+static const char * const desc_lookup_text[] = {
        "OK",
        "FAIL",
        "BAD_PARAM",
@@ -1572,7 +1589,7 @@ static const char *desc_lookup_text[] = {
        "NMI_INTERRUPT_DATA_ACTION_PT",
        "NMI_TRM_HW_ER",
        "NMI_INTERRUPT_TRM",
-       "NMI_INTERRUPT_BREAK_POINT"
+       "NMI_INTERRUPT_BREAK_POINT",
        "DEBUG_0",
        "DEBUG_1",
        "DEBUG_2",
@@ -1925,8 +1942,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
                adv_cmd.critical_temperature_exit =
                        cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
 
-               ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
-                                      sizeof(adv_cmd), &adv_cmd);
+               ret = trans_send_cmd_pdu(priv,
+                                      REPLY_CT_KILL_CONFIG_CMD,
+                                      CMD_SYNC, sizeof(adv_cmd), &adv_cmd);
                if (ret)
                        IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
                else
@@ -1940,8 +1958,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
                cmd.critical_temperature_R =
                        cpu_to_le32(priv->hw_params.ct_kill_threshold);
 
-               ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
-                                      sizeof(cmd), &cmd);
+               ret = trans_send_cmd_pdu(priv,
+                                      REPLY_CT_KILL_CONFIG_CMD,
+                                      CMD_SYNC, sizeof(cmd), &cmd);
                if (ret)
                        IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
                else
@@ -1965,7 +1984,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
        calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
        calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
 
-       return iwl_send_cmd(priv, &cmd);
+       return trans_send_cmd(priv, &cmd);
 }
 
 
@@ -1996,11 +2015,18 @@ int iwl_alive_start(struct iwl_priv *priv)
        if (priv->cfg->bt_params &&
            priv->cfg->bt_params->advanced_bt_coexist) {
                /* Configure Bluetooth device coexistence support */
+               if (priv->cfg->bt_params->bt_sco_disable)
+                       priv->bt_enable_pspoll = false;
+               else
+                       priv->bt_enable_pspoll = true;
+
                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;
+               priv->cur_rssi_ctx = NULL;
+
                iwlagn_send_prio_tbl(priv);
 
                /* FIXME: w/a to force change uCode BT state machine */
@@ -2012,7 +2038,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);
 
@@ -2021,8 +2053,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 =
@@ -2036,16 +2067,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);
@@ -2087,6 +2109,8 @@ static void __iwl_down(struct iwl_priv *priv)
 
        /* reset BT coex data */
        priv->bt_status = 0;
+       priv->cur_rssi_ctx = NULL;
+       priv->bt_is_sco = 0;
        if (priv->cfg->bt_params)
                priv->bt_traffic_load =
                         priv->cfg->bt_params->bt_init_traffic_load;
@@ -2262,6 +2286,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
        u8 bt_ci_compliance;
        u8 bt_load;
        u8 bt_status;
+       bool bt_is_sco;
 
        lockdep_assert_held(&priv->mutex);
 
@@ -2282,6 +2307,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
        bt_ci_compliance = priv->bt_ci_compliance;
        bt_load = priv->bt_traffic_load;
        bt_status = priv->bt_status;
+       bt_is_sco = priv->bt_is_sco;
 
        __iwl_down(priv);
 
@@ -2289,6 +2315,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
        priv->bt_ci_compliance = bt_ci_compliance;
        priv->bt_traffic_load = bt_load;
        priv->bt_status = bt_status;
+       priv->bt_is_sco = bt_is_sco;
 }
 
 static void iwl_bg_restart(struct work_struct *data)
@@ -3200,9 +3227,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
        init_timer(&priv->watchdog);
        priv->watchdog.data = (unsigned long)priv;
        priv->watchdog.function = iwl_bg_watchdog;
-
-       tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-               iwl_irq_tasklet, (unsigned long)priv);
 }
 
 static void iwl_cancel_deferred_work(struct iwl_priv *priv)
@@ -3270,9 +3294,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);
 
@@ -3317,6 +3339,29 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
        kfree(priv->beacon_cmd);
 }
 
+static void iwl_mac_rssi_callback(struct ieee80211_hw *hw,
+                          enum ieee80211_rssi_event rssi_event)
+{
+       struct iwl_priv *priv = hw->priv;
+
+       mutex_lock(&priv->mutex);
+
+       if (priv->cfg->bt_params &&
+                       priv->cfg->bt_params->advanced_bt_coexist) {
+               if (rssi_event == RSSI_EVENT_LOW)
+                       priv->bt_enable_pspoll = true;
+               else if (rssi_event == RSSI_EVENT_HIGH)
+                       priv->bt_enable_pspoll = false;
+
+               iwlagn_send_advance_bt_config(priv);
+       } else {
+               IWL_DEBUG_MAC80211(priv, "Advanced BT coex disabled,"
+                               "ignoring RSSI callback\n");
+       }
+
+       mutex_unlock(&priv->mutex);
+}
+
 struct ieee80211_ops iwlagn_hw_ops = {
        .tx = iwlagn_mac_tx,
        .start = iwlagn_mac_start,
@@ -3342,6 +3387,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
        .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,
+       .rssi_callback = iwl_mac_rssi_callback,
        CFG80211_TESTMODE_CMD(iwl_testmode_cmd)
        CFG80211_TESTMODE_DUMP(iwl_testmode_dump)
 };
@@ -3507,6 +3553,10 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
        priv->cfg = cfg;
        priv->inta_mask = CSR_INI_SET_MASK;
 
+       err = iwl_trans_register(priv);
+       if (err)
+               goto out_free_priv;
+
        /* is antenna coupling more than 35dB ? */
        priv->bt_ant_couple_ok =
                (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
@@ -3601,15 +3651,6 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
        /********************
         * 7. Setup services
         ********************/
-       iwl_alloc_isr_ict(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.irq);
-               goto out_uninit_drv;
-       }
-
        iwl_setup_deferred_work(priv);
        iwl_setup_rx_handlers(priv);
        iwl_testmode_init(priv);
@@ -3640,19 +3681,18 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
 
        return 0;
 
- out_destroy_workqueue:
+out_destroy_workqueue:
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
-       free_irq(priv->bus.irq, priv);
-       iwl_free_isr_ict(priv);
- out_uninit_drv:
        iwl_uninit_drv(priv);
- out_free_eeprom:
+out_free_eeprom:
        iwl_eeprom_free(priv);
- out_free_traffic_mem:
+out_free_traffic_mem:
        iwl_free_traffic_mem(priv);
+       trans_free(priv);
+out_free_priv:
        ieee80211_free_hw(priv->hw);
- out:
+out:
        return err;
 }
 
@@ -3694,17 +3734,15 @@ void __devexit iwl_remove(struct iwl_priv * priv)
        iwl_disable_interrupts(priv);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       iwl_synchronize_irq(priv);
+       trans_sync_irq(priv);
 
        iwl_dealloc_ucode(priv);
 
-       if (priv->rxq.bd)
-               iwlagn_rx_queue_free(priv, &priv->rxq);
-       iwlagn_hw_txq_ctx_free(priv);
+       trans_rx_free(priv);
+       trans_tx_free(priv);
 
        iwl_eeprom_free(priv);
 
-
        /*netif_stop_queue(dev); */
        flush_workqueue(priv->workqueue);
 
@@ -3715,13 +3753,12 @@ void __devexit iwl_remove(struct iwl_priv * priv)
        priv->workqueue = NULL;
        iwl_free_traffic_mem(priv);
 
-       free_irq(priv->bus.irq, priv);
+       trans_free(priv);
+
        priv->bus.ops->set_drv_data(&priv->bus, NULL);
 
        iwl_uninit_drv(priv);
 
-       iwl_free_isr_ict(priv);
-
        dev_kfree_skb(priv->beacon_skb);
 
        ieee80211_free_hw(priv->hw);
@@ -3802,6 +3839,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