]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/iwlwifi/iwl-agn.c
iwlwifi: log stop / wake queues
[karo-tx-linux.git] / drivers / net / wireless / iwlwifi / iwl-agn.c
index c3040ad86e8999414ff188dcd27ef3716a864e98..6ed2f782177be26b4d21f432e0ad5e816c46fd8b 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/div64.h>
 
 #include "iwl-eeprom.h"
-#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
@@ -133,7 +132,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
         * beacon contents.
         */
 
-       lockdep_assert_held(&priv->shrd->mutex);
+       lockdep_assert_held(&priv->mutex);
 
        if (!priv->beacon_ctx) {
                IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
@@ -198,7 +197,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_trans_send_cmd(trans(priv), &cmd);
+       return iwl_dvm_send_cmd(priv, &cmd);
 }
 
 static void iwl_bg_beacon_update(struct work_struct *work)
@@ -207,7 +206,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
                container_of(work, struct iwl_priv, beacon_update);
        struct sk_buff *beacon;
 
-       mutex_lock(&priv->shrd->mutex);
+       mutex_lock(&priv->mutex);
        if (!priv->beacon_ctx) {
                IWL_ERR(priv, "updating beacon w/o beacon context!\n");
                goto out;
@@ -237,7 +236,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
 
        iwlagn_send_beacon_cmd(priv);
  out:
-       mutex_unlock(&priv->shrd->mutex);
+       mutex_unlock(&priv->mutex);
 }
 
 static void iwl_bg_bt_runtime_config(struct work_struct *work)
@@ -260,7 +259,7 @@ 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->shrd->mutex);
+       mutex_lock(&priv->mutex);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
                goto out;
@@ -284,7 +283,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
 
        iwlagn_send_advance_bt_config(priv);
 out:
-       mutex_unlock(&priv->shrd->mutex);
+       mutex_unlock(&priv->mutex);
 }
 
 /**
@@ -328,14 +327,13 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
 
        /* Make sure device is powered up for SRAM reads */
        spin_lock_irqsave(&trans(priv)->reg_lock, reg_flags);
-       if (iwl_grab_nic_access(trans(priv))) {
+       if (unlikely(!iwl_grab_nic_access(trans(priv)))) {
                spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags);
                return;
        }
 
        /* Set starting address; reads will auto-increment */
        iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, ptr);
-       rmb();
 
        /*
         * Refuse to read more than would have fit into the log from
@@ -354,11 +352,12 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
                ev = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
                time = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
                if (mode == 0) {
-                       trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev);
+                       trace_iwlwifi_dev_ucode_cont_event(
+                                       trans(priv)->dev, 0, time, ev);
                } else {
                        data = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
-                       trace_iwlwifi_dev_ucode_cont_event(priv, time,
-                                                          data, ev);
+                       trace_iwlwifi_dev_ucode_cont_event(
+                                       trans(priv)->dev, time, data, ev);
                }
        }
        /* Allow device to power down */
@@ -423,7 +422,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
                else
                        priv->event_log.wraps_once_count++;
 
-               trace_iwlwifi_dev_ucode_wrap_event(priv,
+               trace_iwlwifi_dev_ucode_wrap_event(trans(priv)->dev,
                                num_wraps - priv->event_log.num_wraps,
                                next_entry, priv->event_log.next_entry);
 
@@ -564,7 +563,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
                adv_cmd.critical_temperature_exit =
                        cpu_to_le32(hw_params(priv).ct_kill_exit_threshold);
 
-               ret = iwl_trans_send_cmd_pdu(trans(priv),
+               ret = iwl_dvm_send_cmd_pdu(priv,
                                       REPLY_CT_KILL_CONFIG_CMD,
                                       CMD_SYNC, sizeof(adv_cmd), &adv_cmd);
                if (ret)
@@ -579,7 +578,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
                cmd.critical_temperature_R =
                        cpu_to_le32(hw_params(priv).ct_kill_threshold);
 
-               ret = iwl_trans_send_cmd_pdu(trans(priv),
+               ret = iwl_dvm_send_cmd_pdu(priv,
                                       REPLY_CT_KILL_CONFIG_CMD,
                                       CMD_SYNC, sizeof(cmd), &cmd);
                if (ret)
@@ -605,7 +604,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_RT_CFG_ALL;
        calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
 
-       return iwl_trans_send_cmd(trans(priv), &cmd);
+       return iwl_dvm_send_cmd(priv, &cmd);
 }
 
 
@@ -617,7 +616,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
 
        if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) {
                IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
-               return iwl_trans_send_cmd_pdu(trans(priv),
+               return iwl_dvm_send_cmd_pdu(priv,
                                        TX_ANT_CONFIGURATION_CMD,
                                        CMD_SYNC,
                                        sizeof(struct iwl_tx_ant_config_cmd),
@@ -775,7 +774,7 @@ void iwl_down(struct iwl_priv *priv)
 
        IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
 
-       lockdep_assert_held(&priv->shrd->mutex);
+       lockdep_assert_held(&priv->mutex);
 
        iwl_scan_cancel_timeout(priv, 200);
 
@@ -845,11 +844,11 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
        struct iwl_priv *priv = container_of(work, struct iwl_priv,
                        run_time_calib_work);
 
-       mutex_lock(&priv->shrd->mutex);
+       mutex_lock(&priv->mutex);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) ||
            test_bit(STATUS_SCANNING, &priv->shrd->status)) {
-               mutex_unlock(&priv->shrd->mutex);
+               mutex_unlock(&priv->mutex);
                return;
        }
 
@@ -858,7 +857,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
                iwl_sensitivity_calibration(priv);
        }
 
-       mutex_unlock(&priv->shrd->mutex);
+       mutex_unlock(&priv->mutex);
 }
 
 void iwlagn_prepare_restart(struct iwl_priv *priv)
@@ -870,7 +869,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv)
        u8 bt_status;
        bool bt_is_sco;
 
-       lockdep_assert_held(&priv->shrd->mutex);
+       lockdep_assert_held(&priv->mutex);
 
        for_each_context(priv, ctx)
                ctx->vif = NULL;
@@ -908,9 +907,9 @@ static void iwl_bg_restart(struct work_struct *data)
                return;
 
        if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) {
-               mutex_lock(&priv->shrd->mutex);
+               mutex_lock(&priv->mutex);
                iwlagn_prepare_restart(priv);
-               mutex_unlock(&priv->shrd->mutex);
+               mutex_unlock(&priv->mutex);
                iwl_cancel_deferred_work(priv);
                ieee80211_restart_hw(priv->hw);
        } else {
@@ -925,7 +924,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv)
 {
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
 
-       lockdep_assert_held(&priv->shrd->mutex);
+       lockdep_assert_held(&priv->mutex);
 
        if (!priv->hw_roc_setup)
                return;
@@ -948,9 +947,9 @@ static void iwlagn_disable_roc_work(struct work_struct *work)
        struct iwl_priv *priv = container_of(work, struct iwl_priv,
                                             hw_roc_disable_work.work);
 
-       mutex_lock(&priv->shrd->mutex);
+       mutex_lock(&priv->mutex);
        iwlagn_disable_roc(priv);
-       mutex_unlock(&priv->shrd->mutex);
+       mutex_unlock(&priv->mutex);
 }
 
 /*****************************************************************************
@@ -976,8 +975,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 
        iwl_setup_scan_deferred_work(priv);
 
-       if (cfg(priv)->lib->bt_setup_deferred_work)
-               cfg(priv)->lib->bt_setup_deferred_work(priv);
+       if (cfg(priv)->bt_params)
+               iwlagn_bt_setup_deferred_work(priv);
 
        init_timer(&priv->statistics_periodic);
        priv->statistics_periodic.data = (unsigned long)priv;
@@ -994,8 +993,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 
 void iwl_cancel_deferred_work(struct iwl_priv *priv)
 {
-       if (cfg(priv)->lib->cancel_deferred_work)
-               cfg(priv)->lib->cancel_deferred_work(priv);
+       if (cfg(priv)->bt_params)
+               iwlagn_bt_cancel_deferred_work(priv);
 
        cancel_work_sync(&priv->run_time_calib_work);
        cancel_work_sync(&priv->beacon_update);
@@ -1010,8 +1009,7 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv)
        del_timer_sync(&priv->ucode_trace);
 }
 
-static void iwl_init_hw_rates(struct iwl_priv *priv,
-                             struct ieee80211_rate *rates)
+static void iwl_init_hw_rates(struct ieee80211_rate *rates)
 {
        int i;
 
@@ -1037,7 +1035,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
 
        spin_lock_init(&priv->sta_lock);
 
-       mutex_init(&priv->shrd->mutex);
+       mutex_init(&priv->mutex);
 
        INIT_LIST_HEAD(&priv->calib_results);
 
@@ -1045,11 +1043,16 @@ static int iwl_init_drv(struct iwl_priv *priv)
        priv->ieee_rates = NULL;
        priv->band = IEEE80211_BAND_2GHZ;
 
+       priv->plcp_delta_threshold =
+               cfg(priv)->base_params->plcp_delta_threshold;
+
        priv->iw_mode = NL80211_IFTYPE_STATION;
        priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
        priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
        priv->agg_tids_count = 0;
 
+       priv->ucode_owner = IWL_OWNERSHIP_DRIVER;
+
        /* initialize force reset */
        priv->force_reset[IWL_RF_RESET].reset_duration =
                IWL_DELAY_NEXT_FORCE_RF_RESET;
@@ -1085,7 +1088,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
                IWL_ERR(priv, "initializing geos failed: %d\n", ret);
                goto err_free_channel_map;
        }
-       iwl_init_hw_rates(priv, priv->ieee_rates);
+       iwl_init_hw_rates(priv->ieee_rates);
 
        return 0;
 
@@ -1099,8 +1102,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
 {
        iwl_free_geos(priv);
        iwl_free_channel_map(priv);
-       if (priv->tx_cmd_pool)
-               kmem_cache_destroy(priv->tx_cmd_pool);
        kfree(priv->scan_cmd);
        kfree(priv->beacon_cmd);
        kfree(rcu_dereference_raw(priv->noa_data));
@@ -1116,6 +1117,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
 
 static void iwl_set_hw_params(struct iwl_priv *priv)
 {
+       if (cfg(priv)->ht_params)
+               hw_params(priv).use_rts_for_aggregation =
+                       cfg(priv)->ht_params->use_rts_for_aggregation;
+
        if (iwlagn_mod_params.amsdu_size_8K)
                hw_params(priv).rx_page_order =
                        get_order(IWL_RX_BUF_SIZE_8K);
@@ -1128,8 +1133,6 @@ static void iwl_set_hw_params(struct iwl_priv *priv)
 
        hw_params(priv).num_ampdu_queues =
                cfg(priv)->base_params->num_of_ampdu_queues;
-       hw_params(priv).shadow_reg_enable =
-               cfg(priv)->base_params->shadow_reg_enable;
        hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout;
 
        /* Device-specific setup */
@@ -1198,7 +1201,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
        op_mode->ops = &iwl_dvm_ops;
        priv = IWL_OP_MODE_GET_DVM(op_mode);
        priv->shrd = trans->shrd;
-       priv->shrd->priv = priv;
        priv->fw = fw;
        /* TODO: remove fw from shared data later */
        priv->shrd->fw = fw;
@@ -1405,6 +1407,60 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
        ieee80211_free_hw(priv->hw);
 }
 
+static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
+{
+       struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+       if (!iwl_check_for_ct_kill(priv)) {
+               IWL_ERR(priv, "Restarting adapter queue is full\n");
+               iwl_nic_error(op_mode);
+       }
+}
+
+static void iwl_nic_config(struct iwl_op_mode *op_mode)
+{
+       struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+       cfg(priv)->lib->nic_config(priv);
+}
+
+static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
+{
+       struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+       set_bit(ac, &priv->transport_queue_stop);
+       ieee80211_stop_queue(priv->hw, ac);
+}
+
+static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
+{
+       struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+       clear_bit(ac, &priv->transport_queue_stop);
+
+       if (!priv->passive_no_rx)
+               ieee80211_wake_queue(priv->hw, ac);
+}
+
+void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
+{
+       int ac;
+
+       if (!priv->passive_no_rx)
+               return;
+
+       for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) {
+               if (!test_bit(ac, &priv->transport_queue_stop)) {
+                       IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d");
+                       ieee80211_wake_queue(priv->hw, ac);
+               } else {
+                       IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d");
+               }
+       }
+
+       priv->passive_no_rx = false;
+}
+
 const struct iwl_op_mode_ops iwl_dvm_ops = {
        .start = iwl_op_mode_dvm_start,
        .stop = iwl_op_mode_dvm_stop,
@@ -1414,6 +1470,8 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
        .hw_rf_kill = iwl_set_hw_rfkill_state,
        .free_skb = iwl_free_skb,
        .nic_error = iwl_nic_error,
+       .cmd_queue_full = iwl_cmd_queue_full,
+       .nic_config = iwl_nic_config,
 };
 
 /*****************************************************************************
@@ -1421,6 +1479,9 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
  * driver and module entry point
  *
  *****************************************************************************/
+
+struct kmem_cache *iwl_tx_cmd_pool;
+
 static int __init iwl_init(void)
 {
 
@@ -1428,20 +1489,27 @@ static int __init iwl_init(void)
        pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
        pr_info(DRV_COPYRIGHT "\n");
 
+       iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd",
+                                           sizeof(struct iwl_device_cmd),
+                                           sizeof(void *), 0, NULL);
+       if (!iwl_tx_cmd_pool)
+               return -ENOMEM;
+
        ret = iwlagn_rate_control_register();
        if (ret) {
                pr_err("Unable to register rate control algorithm: %d\n", ret);
-               return ret;
+               goto error_rc_register;
        }
 
        ret = iwl_pci_register_driver();
-
        if (ret)
-               goto error_register;
+               goto error_pci_register;
        return ret;
 
-error_register:
+error_pci_register:
        iwlagn_rate_control_unregister();
+error_rc_register:
+       kmem_cache_destroy(iwl_tx_cmd_pool);
        return ret;
 }
 
@@ -1449,6 +1517,7 @@ static void __exit iwl_exit(void)
 {
        iwl_pci_unregister_driver();
        iwlagn_rate_control_unregister();
+       kmem_cache_destroy(iwl_tx_cmd_pool);
 }
 
 module_exit(iwl_exit);
@@ -1462,8 +1531,6 @@ MODULE_PARM_DESC(debug, "debug output mask");
 
 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_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO);
-MODULE_PARM_DESC(queues_num, "number of hw queues.");
 module_param_named(11n_disable, iwlagn_mod_params.disable_11n, uint, S_IRUGO);
 MODULE_PARM_DESC(11n_disable,
        "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");