#include <asm/div64.h>
-#include "iwl-ucode.h"
#include "iwl-eeprom.h"
-#include "iwl-wifi.h"
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
* 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");
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)
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;
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)
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;
iwlagn_send_advance_bt_config(priv);
out:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
/**
/* 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
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 */
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);
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)
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)
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);
}
.valid = cpu_to_le32(valid_tx_ant),
};
- if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) > 1) {
+ 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),
priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
priv->cur_rssi_ctx = NULL;
- iwl_send_prio_tbl(trans(priv));
+ iwl_send_prio_tbl(priv);
/* FIXME: w/a to force change uCode BT state machine */
- ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN,
+ ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret)
return ret;
- ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_CLOSE,
+ ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret)
return ret;
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);
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;
}
iwl_sensitivity_calibration(priv);
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
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;
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 {
{
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;
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);
}
/*****************************************************************************
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;
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);
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;
spin_lock_init(&priv->sta_lock);
- mutex_init(&priv->shrd->mutex);
+ mutex_init(&priv->mutex);
- INIT_LIST_HEAD(&trans(priv)->calib_results);
+ INIT_LIST_HEAD(&priv->calib_results);
priv->ieee_channels = NULL;
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;
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;
{
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));
+ iwl_calib_free_results(priv);
#ifdef CONFIG_IWLWIFI_DEBUGFS
kfree(priv->wowlan_sram);
#endif
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);
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 */
#endif
}
-static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
+static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
+ const struct iwl_fw *fw)
{
- struct iwl_fw *fw = &nic(trans)->fw;
int err = 0;
struct iwl_priv *priv;
struct ieee80211_hw *hw;
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;
iwl_trans_configure(trans(priv), 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))
+ ieee80211_wake_queue(priv->hw, ac);
+ }
+
+ 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,
.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,
};
/*****************************************************************************
* driver and module entry point
*
*****************************************************************************/
+
+struct kmem_cache *iwl_tx_cmd_pool;
+
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;
}
{
iwl_pci_unregister_driver();
iwlagn_rate_control_unregister();
+ kmem_cache_destroy(iwl_tx_cmd_pool);
}
module_exit(iwl_exit);
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");