summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-07-31 06:26:55 +0400
committerDavid S. Miller <davem@davemloft.net>2009-07-31 06:26:55 +0400
commit2f6d7c1b34403b97fa57473edcb6749d1db5ace3 (patch)
tree97da33c077b08b72a361ff5a4542b86d190b0164 /drivers/net/wireless/iwlwifi
parentdf597efb5737063497f1a4f7c996cc9aec294230 (diff)
parent1e4247d457c6a42e4a05cb7dfa4e6ea1fa65c112 (diff)
downloadlinux-2f6d7c1b34403b97fa57473edcb6749d1db5ace3.tar.xz
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c77
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-led.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c18
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c45
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c59
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c85
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c23
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c35
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c84
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h116
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c63
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c526
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h93
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c48
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c100
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c20
25 files changed, 1222 insertions, 228 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index e092af09d6bf..99310c033253 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -9,6 +9,9 @@ config IWLWIFI
config IWLWIFI_LEDS
bool "Enable LED support in iwlagn and iwl3945 drivers"
depends on IWLWIFI
+ default y
+ ---help---
+ Select this if you want LED support.
config IWLWIFI_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwlagn driver"
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index a899be914ebf..5f7c52053c18 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -55,13 +55,88 @@
#define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode"
#define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api)
+
+/*
+ * For 1000, use advance thermal throttling critical temperature threshold,
+ * but legacy thermal management implementation for now.
+ * This is for the reason of 1000 uCode using advance thermal throttling API
+ * but not implement ct_kill_exit based on ct_kill exit temperature
+ * so the thermal throttling will still based on legacy thermal throttling
+ * management.
+ * The code here need to be modified once 1000 uCode has the advanced thermal
+ * throttling algorithm in place
+ */
+static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
+{
+ /* want Celsius */
+ priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
+ priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
+}
+
+static struct iwl_lib_ops iwl1000_lib = {
+ .set_hw_params = iwl5000_hw_set_hw_params,
+ .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
+ .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
+ .txq_set_sched = iwl5000_txq_set_sched,
+ .txq_agg_enable = iwl5000_txq_agg_enable,
+ .txq_agg_disable = iwl5000_txq_agg_disable,
+ .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
+ .txq_free_tfd = iwl_hw_txq_free_tfd,
+ .txq_init = iwl_hw_tx_queue_init,
+ .rx_handler_setup = iwl5000_rx_handler_setup,
+ .setup_deferred_work = iwl5000_setup_deferred_work,
+ .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
+ .load_ucode = iwl5000_load_ucode,
+ .init_alive_start = iwl5000_init_alive_start,
+ .alive_notify = iwl5000_alive_notify,
+ .send_tx_power = iwl5000_send_tx_power,
+ .update_chain_flags = iwl_update_chain_flags,
+ .apm_ops = {
+ .init = iwl5000_apm_init,
+ .reset = iwl5000_apm_reset,
+ .stop = iwl5000_apm_stop,
+ .config = iwl5000_nic_config,
+ .set_pwr_src = iwl_set_pwr_src,
+ },
+ .eeprom_ops = {
+ .regulatory_bands = {
+ EEPROM_5000_REG_BAND_1_CHANNELS,
+ EEPROM_5000_REG_BAND_2_CHANNELS,
+ EEPROM_5000_REG_BAND_3_CHANNELS,
+ EEPROM_5000_REG_BAND_4_CHANNELS,
+ EEPROM_5000_REG_BAND_5_CHANNELS,
+ EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
+ EEPROM_5000_REG_BAND_52_FAT_CHANNELS
+ },
+ .verify_signature = iwlcore_eeprom_verify_signature,
+ .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
+ .release_semaphore = iwlcore_eeprom_release_semaphore,
+ .calib_version = iwl5000_eeprom_calib_version,
+ .query_addr = iwl5000_eeprom_query_addr,
+ },
+ .post_associate = iwl_post_associate,
+ .isr = iwl_isr_ict,
+ .config_ap = iwl_config_ap,
+ .temp_ops = {
+ .temperature = iwl5000_temperature,
+ .set_ct_kill = iwl1000_set_ct_threshold,
+ },
+};
+
+static struct iwl_ops iwl1000_ops = {
+ .ucode = &iwl5000_ucode,
+ .lib = &iwl1000_lib,
+ .hcmd = &iwl5000_hcmd,
+ .utils = &iwl5000_hcmd_utils,
+};
+
struct iwl_cfg iwl1000_bgn_cfg = {
.name = "1000 Series BGN",
.fw_name_pre = IWL1000_FW_PRE,
.ucode_api_max = IWL1000_UCODE_API_MAX,
.ucode_api_min = IWL1000_UCODE_API_MIN,
.sku = IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl5000_ops,
+ .ops = &iwl1000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
index 225e5f889346..8c29ded7d02c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
@@ -79,11 +79,10 @@ static const struct {
#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/
#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
-static int iwl3945_led_cmd_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
- struct sk_buff *skb)
+static void iwl3945_led_cmd_callback(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb)
{
- return 1;
}
static inline int iwl3945_brightness_to_idx(enum led_brightness brightness)
@@ -99,8 +98,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv,
.id = REPLY_LEDS_CMD,
.len = sizeof(struct iwl_led_cmd),
.data = led_cmd,
- .meta.flags = CMD_ASYNC,
- .meta.u.callback = iwl3945_led_cmd_callback,
+ .flags = CMD_ASYNC,
+ .callback = iwl3945_led_cmd_callback,
};
return iwl_send_cmd(priv, &cmd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 8ee403cd9b99..e1b0ef3c56a3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -749,8 +749,8 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
/* Unmap tx_cmd */
if (counter)
pci_unmap_single(dev,
- pci_unmap_addr(&txq->cmd[index]->meta, mapping),
- pci_unmap_len(&txq->cmd[index]->meta, len),
+ pci_unmap_addr(&txq->meta[index], mapping),
+ pci_unmap_len(&txq->meta[index], len),
PCI_DMA_TODEVICE);
/* unmap chunks if any */
@@ -774,9 +774,11 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
* iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
*
*/
-void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_hdr *hdr, int sta_id, int tx_id)
+void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_hdr *hdr,
+ int sta_id, int tx_id)
{
u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value;
u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1);
@@ -1858,7 +1860,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
struct iwl_host_cmd cmd = {
.id = REPLY_RXON_ASSOC,
.len = sizeof(rxon_assoc),
- .meta.flags = CMD_WANT_SKB,
+ .flags = CMD_WANT_SKB,
.data = &rxon_assoc,
};
const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
@@ -1882,14 +1884,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
if (rc)
return rc;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
rc = -EIO;
}
priv->alloc_rxb_skb--;
- dev_kfree_skb_any(cmd.meta.u.skb);
+ dev_kfree_skb_any(cmd.reply_skb);
return rc;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index f2ffc48cbaf8..f24036909916 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -254,10 +254,11 @@ extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl3945_frame *frame, u8 rate);
-void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_hdr *hdr,
- int sta_id, int tx_id);
+void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_hdr *hdr,
+ int sta_id, int tx_id);
extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index c30a1b960576..670214823cb9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -776,7 +776,8 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
{
/* want Kelvin */
- priv->hw_params.ct_kill_threshold = CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD);
+ priv->hw_params.ct_kill_threshold =
+ CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY);
}
/**
@@ -1796,6 +1797,7 @@ static void iwl4965_temperature_calib(struct iwl_priv *priv)
}
priv->temperature = temp;
+ iwl_tt_handler(priv);
set_bit(STATUS_TEMPERATURE, &priv->status);
if (!priv->disable_tx_power_cal &&
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 702db07fa382..ddd64fef3039 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -91,7 +91,7 @@ static int iwl5000_apm_stop_master(struct iwl_priv *priv)
}
-static int iwl5000_apm_init(struct iwl_priv *priv)
+int iwl5000_apm_init(struct iwl_priv *priv)
{
int ret = 0;
@@ -137,7 +137,7 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
}
/* FIXME: this is identical to 4965 */
-static void iwl5000_apm_stop(struct iwl_priv *priv)
+void iwl5000_apm_stop(struct iwl_priv *priv)
{
unsigned long flags;
@@ -156,7 +156,7 @@ static void iwl5000_apm_stop(struct iwl_priv *priv)
}
-static int iwl5000_apm_reset(struct iwl_priv *priv)
+int iwl5000_apm_reset(struct iwl_priv *priv)
{
int ret = 0;
@@ -198,7 +198,7 @@ out:
}
-static void iwl5000_nic_config(struct iwl_priv *priv)
+void iwl5000_nic_config(struct iwl_priv *priv)
{
unsigned long flags;
u16 radio_cfg;
@@ -290,7 +290,7 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
return (address & ADDRESS_MSK) + (offset << 1);
}
-static u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv)
+u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv)
{
struct iwl_eeprom_calib_hdr {
u8 version;
@@ -436,7 +436,7 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
.nrg_th_ofdm = 95,
};
-static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
+const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
size_t offset)
{
u32 address = eeprom_indirect_address(priv, offset);
@@ -447,7 +447,7 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
{
const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
- s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD) -
+ s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) -
iwl_temp_calib_to_offset(priv);
priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef;
@@ -456,7 +456,7 @@ static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
{
/* want Celsius */
- priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
+ priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
}
/*
@@ -631,7 +631,7 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv,
return ret;
}
-static int iwl5000_load_ucode(struct iwl_priv *priv)
+int iwl5000_load_ucode(struct iwl_priv *priv)
{
int ret = 0;
@@ -658,7 +658,7 @@ static int iwl5000_load_ucode(struct iwl_priv *priv)
return ret;
}
-static void iwl5000_init_alive_start(struct iwl_priv *priv)
+void iwl5000_init_alive_start(struct iwl_priv *priv)
{
int ret = 0;
@@ -734,7 +734,7 @@ static int iwl5000_send_wimax_coex(struct iwl_priv *priv)
sizeof(coex_cmd), &coex_cmd);
}
-static int iwl5000_alive_notify(struct iwl_priv *priv)
+int iwl5000_alive_notify(struct iwl_priv *priv)
{
u32 a;
unsigned long flags;
@@ -821,7 +821,7 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
return 0;
}
-static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
+int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
{
if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) ||
(priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
@@ -892,7 +892,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
/**
* iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/
-static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
+void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
u16 byte_cnt)
{
@@ -932,7 +932,7 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
}
-static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
+void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq)
{
struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
@@ -987,7 +987,7 @@ static void iwl5000_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id)
(1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
}
-static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
+int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
int tx_fifo, int sta_id, int tid, u16 ssn_idx)
{
unsigned long flags;
@@ -1048,7 +1048,7 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
return 0;
}
-static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
+int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
u16 ssn_idx, u8 tx_fifo)
{
if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
@@ -1091,7 +1091,7 @@ u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
* Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
* must be called under priv->lock and mac access
*/
-static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
+void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
{
iwl_write_prph(priv, IWL50_SCD_TXFACT, mask);
}
@@ -1312,13 +1312,13 @@ u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len)
return len;
}
-static void iwl5000_setup_deferred_work(struct iwl_priv *priv)
+void iwl5000_setup_deferred_work(struct iwl_priv *priv)
{
/* in 5000 the tx power calibration is done in uCode */
priv->disable_tx_power_cal = 1;
}
-static void iwl5000_rx_handler_setup(struct iwl_priv *priv)
+void iwl5000_rx_handler_setup(struct iwl_priv *priv)
{
/* init calibration handlers */
priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
@@ -1329,7 +1329,7 @@ static void iwl5000_rx_handler_setup(struct iwl_priv *priv)
}
-static int iwl5000_hw_valid_rtc_data_addr(u32 addr)
+int iwl5000_hw_valid_rtc_data_addr(u32 addr)
{
return (addr >= IWL50_RTC_DATA_LOWER_BOUND) &&
(addr < IWL50_RTC_DATA_UPPER_BOUND);
@@ -1381,7 +1381,7 @@ static int iwl5000_send_rxon_assoc(struct iwl_priv *priv)
return ret;
}
-static int iwl5000_send_tx_power(struct iwl_priv *priv)
+int iwl5000_send_tx_power(struct iwl_priv *priv)
{
struct iwl5000_tx_power_dbm_cmd tx_power_cmd;
u8 tx_ant_cfg_cmd;
@@ -1401,10 +1401,11 @@ static int iwl5000_send_tx_power(struct iwl_priv *priv)
NULL);
}
-static void iwl5000_temperature(struct iwl_priv *priv)
+void iwl5000_temperature(struct iwl_priv *priv)
{
/* store temperature from statistics (in Celsius) */
priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
+ iwl_tt_handler(priv);
}
static void iwl5150_temperature(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 26c5d4a60d17..59ff73536f3a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -61,6 +61,63 @@
#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
+static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
+{
+ /* want Celsius */
+ priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
+ priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
+}
+
+static struct iwl_lib_ops iwl6000_lib = {
+ .set_hw_params = iwl5000_hw_set_hw_params,
+ .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
+ .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
+ .txq_set_sched = iwl5000_txq_set_sched,
+ .txq_agg_enable = iwl5000_txq_agg_enable,
+ .txq_agg_disable = iwl5000_txq_agg_disable,
+ .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
+ .txq_free_tfd = iwl_hw_txq_free_tfd,
+ .txq_init = iwl_hw_tx_queue_init,
+ .rx_handler_setup = iwl5000_rx_handler_setup,
+ .setup_deferred_work = iwl5000_setup_deferred_work,
+ .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
+ .load_ucode = iwl5000_load_ucode,
+ .init_alive_start = iwl5000_init_alive_start,
+ .alive_notify = iwl5000_alive_notify,
+ .send_tx_power = iwl5000_send_tx_power,
+ .update_chain_flags = iwl_update_chain_flags,
+ .apm_ops = {
+ .init = iwl5000_apm_init,
+ .reset = iwl5000_apm_reset,
+ .stop = iwl5000_apm_stop,
+ .config = iwl5000_nic_config,
+ .set_pwr_src = iwl_set_pwr_src,
+ },
+ .eeprom_ops = {
+ .regulatory_bands = {
+ EEPROM_5000_REG_BAND_1_CHANNELS,
+ EEPROM_5000_REG_BAND_2_CHANNELS,
+ EEPROM_5000_REG_BAND_3_CHANNELS,
+ EEPROM_5000_REG_BAND_4_CHANNELS,
+ EEPROM_5000_REG_BAND_5_CHANNELS,
+ EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
+ EEPROM_5000_REG_BAND_52_FAT_CHANNELS
+ },
+ .verify_signature = iwlcore_eeprom_verify_signature,
+ .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
+ .release_semaphore = iwlcore_eeprom_release_semaphore,
+ .calib_version = iwl5000_eeprom_calib_version,
+ .query_addr = iwl5000_eeprom_query_addr,
+ },
+ .post_associate = iwl_post_associate,
+ .isr = iwl_isr_ict,
+ .config_ap = iwl_config_ap,
+ .temp_ops = {
+ .temperature = iwl5000_temperature,
+ .set_ct_kill = iwl6000_set_ct_threshold,
+ },
+};
+
static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = {
.get_hcmd_size = iwl5000_get_hcmd_size,
.build_addsta_hcmd = iwl5000_build_addsta_hcmd,
@@ -70,7 +127,7 @@ static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = {
static struct iwl_ops iwl6000_ops = {
.ucode = &iwl5000_ucode,
- .lib = &iwl5000_lib,
+ .lib = &iwl6000_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl6000_hcmd_utils,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 63280411fd58..52a4810274e9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -177,7 +177,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
struct sk_buff *skb,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta);
-static void rs_fill_link_cmd(const struct iwl_priv *priv,
+static void rs_fill_link_cmd(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
@@ -1398,6 +1398,12 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
int ret = 0;
u8 update_search_tbl_counter = 0;
+ if (!iwl_ht_enabled(priv))
+ /* stay in Legacy */
+ tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
+ else if (iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE &&
+ tbl->action > IWL_LEGACY_SWITCH_SISO)
+ tbl->action = IWL_LEGACY_SWITCH_SISO;
for (; ;) {
lq_sta->action_counter++;
switch (tbl->action) {
@@ -1529,6 +1535,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
u8 update_search_tbl_counter = 0;
int ret;
+ if (iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE &&
+ tbl->action > IWL_SISO_SWITCH_ANTENNA2) {
+ /* stay in SISO */
+ tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+ }
for (;;) {
lq_sta->action_counter++;
switch (tbl->action) {
@@ -1663,6 +1674,12 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
u8 update_search_tbl_counter = 0;
int ret;
+ if ((iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE) &&
+ (tbl->action < IWL_MIMO2_SWITCH_SISO_A ||
+ tbl->action > IWL_MIMO2_SWITCH_SISO_C)) {
+ /* switch in SISO */
+ tbl->action = IWL_MIMO2_SWITCH_SISO_A;
+ }
for (;;) {
lq_sta->action_counter++;
switch (tbl->action) {
@@ -1799,6 +1816,12 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
int ret;
u8 update_search_tbl_counter = 0;
+ if ((iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE) &&
+ (tbl->action < IWL_MIMO3_SWITCH_SISO_A ||
+ tbl->action > IWL_MIMO3_SWITCH_SISO_C)) {
+ /* switch in SISO */
+ tbl->action = IWL_MIMO3_SWITCH_SISO_A;
+ }
for (;;) {
lq_sta->action_counter++;
switch (tbl->action) {
@@ -2003,6 +2026,25 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
}
/*
+ * setup rate table in uCode
+ * return rate_n_flags as used in the table
+ */
+static u32 rs_update_rate_tbl(struct iwl_priv *priv,
+ struct iwl_lq_sta *lq_sta,
+ struct iwl_scale_tbl_info *tbl,
+ int index, u8 is_green)
+{
+ u32 rate;
+
+ /* Update uCode's rate table. */
+ rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
+ rs_fill_link_cmd(priv, lq_sta, rate);
+ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+
+ return rate;
+}
+
+/*
* Do rate scaling and search for new modulation mode.
*/
static void rs_rate_scale_perform(struct iwl_priv *priv,
@@ -2098,6 +2140,16 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
if (!((1 << index) & rate_scale_index_msk)) {
IWL_ERR(priv, "Current Rate is not valid\n");
+ if (lq_sta->search_better_tbl) {
+ /* revert to active table if search table is not valid*/
+ tbl->lq_type = LQ_NONE;
+ lq_sta->search_better_tbl = 0;
+ tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+ /* get "active" rate info */
+ index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
+ rate = rs_update_rate_tbl(priv, lq_sta,
+ tbl, index, is_green);
+ }
return;
}
@@ -2149,8 +2201,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
tbl->expected_tpt[index] + 64) / 128));
/* If we are searching for better modulation mode, check success. */
- if (lq_sta->search_better_tbl) {
-
+ if (lq_sta->search_better_tbl &&
+ (iwl_tx_ant_restriction(priv) == IWL_TX_MULTI)) {
/* If good success, continue using the "search" mode;
* no need to send new link quality command, since we're
* continuing to use the setup that we've been trying. */
@@ -2278,7 +2330,11 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
((sr > IWL_RATE_HIGH_TH) ||
(current_tpt > (100 * tbl->expected_tpt[low]))))
scale_action = 0;
-
+ if (!iwl_ht_enabled(priv) && !is_legacy(tbl->lq_type))
+ scale_action = -1;
+ if (iwl_tx_ant_restriction(priv) != IWL_TX_MULTI &&
+ (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type)))
+ scale_action = -1;
switch (scale_action) {
case -1:
/* Decrease starting rate, update uCode's rate table */
@@ -2308,15 +2364,15 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
lq_update:
/* Replace uCode's rate table for the destination station. */
- if (update_lq) {
- rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
- rs_fill_link_cmd(priv, lq_sta, rate);
- iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
- }
-
- /* Should we stay with this modulation mode, or search for a new one? */
- rs_stay_in_table(lq_sta);
+ if (update_lq)
+ rate = rs_update_rate_tbl(priv, lq_sta,
+ tbl, index, is_green);
+ if (iwl_tx_ant_restriction(priv) == IWL_TX_MULTI) {
+ /* Should we stay with this modulation mode,
+ * or search for a new one? */
+ rs_stay_in_table(lq_sta);
+ }
/*
* Search for new modulation mode if we're:
* 1) Not changing rates right now
@@ -2373,7 +2429,8 @@ lq_update:
* have been tried and compared, stay in this best modulation
* mode for a while before next round of mode comparisons. */
if (lq_sta->enable_counter &&
- (lq_sta->action_counter >= tbl1->max_search)) {
+ (lq_sta->action_counter >= tbl1->max_search) &&
+ iwl_ht_enabled(priv)) {
if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
(lq_sta->tx_agg_tid_en & (1 << tid)) &&
(tid != MAX_TID_COUNT)) {
@@ -2659,7 +2716,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
rs_initialize_lq(priv, conf, sta, lq_sta);
}
-static void rs_fill_link_cmd(const struct iwl_priv *priv,
+static void rs_fill_link_cmd(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta, u32 new_rate)
{
struct iwl_scale_tbl_info tbl_type;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 44c7f236a7a3..4cb1a1b73483 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -442,8 +442,8 @@ void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
/* Unmap tx_cmd */
if (num_tbs)
pci_unmap_single(dev,
- pci_unmap_addr(&txq->cmd[index]->meta, mapping),
- pci_unmap_len(&txq->cmd[index]->meta, len),
+ pci_unmap_addr(&txq->meta[index], mapping),
+ pci_unmap_len(&txq->meta[index], len),
PCI_DMA_BIDIRECTIONAL);
/* Unmap chunks, if any. */
@@ -637,7 +637,6 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
unsigned long status = priv->status;
- unsigned long reg_flags;
IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n",
(flags & HW_CARD_DISABLED) ? "Kill" : "On",
@@ -657,19 +656,12 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
iwl_write_direct32(priv, HBUS_TARG_MBX_C,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-
- }
-
- if (flags & RF_CARD_DISABLED) {
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
- CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
- iwl_read32(priv, CSR_UCODE_DRV_GP1);
- spin_lock_irqsave(&priv->reg_lock, reg_flags);
- if (!iwl_grab_nic_access(priv))
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
}
+ if (flags & RF_CARD_DISABLED)
+ iwl_tt_enter_ct_kill(priv);
}
+ if (!(flags & RF_CARD_DISABLED))
+ iwl_tt_exit_ct_kill(priv);
if (flags & HW_CARD_DISABLED)
set_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -3015,6 +3007,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
test_bit(STATUS_RF_KILL_HW, &priv->status));
iwl_power_initialize(priv);
+ iwl_tt_initialize(priv);
return 0;
out_remove_sysfs:
@@ -3067,6 +3060,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
iwl_down(priv);
}
+ iwl_tt_exit(priv);
+
/* make sure we flush any pending irq or
* tasklet for the driver
*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index f8bf592e939c..13180d6ee2f7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -86,7 +86,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
struct iwl_host_cmd hcmd = {
.id = REPLY_PHY_CALIBRATION_CMD,
- .meta.flags = CMD_SIZE_HUGE,
+ .flags = CMD_SIZE_HUGE,
};
for (i = 0; i < IWL_CALIB_MAX; i++) {
@@ -419,7 +419,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
struct iwl_host_cmd cmd_out = {
.id = SENSITIVITY_CMD,
.len = sizeof(struct iwl_sensitivity_cmd),
- .meta.flags = CMD_ASYNC,
+ .flags = CMD_ASYNC,
.data = &cmd,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index ebb2fbce5365..39ede5727fe4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -2413,6 +2413,13 @@ struct iwl_ct_kill_config {
__le32 critical_temperature_R;
} __attribute__ ((packed));
+/* 1000, and 6x00 */
+struct iwl_ct_kill_throttling_config {
+ __le32 critical_temperature_exit;
+ __le32 reserved;
+ __le32 critical_temperature_enter;
+} __attribute__ ((packed));
+
/******************************************************************************
* (8)
* Scan Commands, Responses, Notifications:
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 6aea02644809..8570d56b3124 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -632,6 +632,10 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
if (!sta_ht_inf->ht_supported)
return 0;
}
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (priv->disable_ht40)
+ return 0;
+#endif
return iwl_is_channel_extension(priv, priv->band,
le16_to_cpu(priv->staging_rxon.channel),
iwl_ht_conf->extension_chan_offset);
@@ -1291,7 +1295,6 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
-#endif
static const char *desc_lookup_text[] = {
"OK",
@@ -1496,6 +1499,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
iwl_print_event_log(priv, 0, next_entry, mode);
}
+#endif
/**
* iwl_irq_handle_error - called for HW or SW error interrupt from card
*/
@@ -2089,7 +2093,7 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags)
u32 stat_flags = 0;
struct iwl_host_cmd cmd = {
.id = REPLY_STATISTICS_CMD,
- .meta.flags = flags,
+ .flags = flags,
.len = sizeof(stat_flags),
.data = (u8 *) &stat_flags,
};
@@ -2224,6 +2228,7 @@ EXPORT_SYMBOL(iwl_verify_ucode);
void iwl_rf_kill_ct_config(struct iwl_priv *priv)
{
struct iwl_ct_kill_config cmd;
+ struct iwl_ct_kill_throttling_config adv_cmd;
unsigned long flags;
int ret = 0;
@@ -2231,10 +2236,28 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
spin_unlock_irqrestore(&priv->lock, flags);
+ priv->power_data.ct_kill_toggle = false;
+
+ switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
+ case CSR_HW_REV_TYPE_1000:
+ case CSR_HW_REV_TYPE_6x00:
+ case CSR_HW_REV_TYPE_6x50:
+ adv_cmd.critical_temperature_enter =
+ cpu_to_le32(priv->hw_params.ct_kill_threshold);
+ 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);
+ break;
+ default:
+ cmd.critical_temperature_R =
+ cpu_to_le32(priv->hw_params.ct_kill_threshold);
- 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);
+ break;
+ }
ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
sizeof(cmd), &cmd);
if (ret)
@@ -2263,7 +2286,7 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
.id = REPLY_CARD_STATE_CMD,
.len = sizeof(u32),
.data = &flags,
- .meta.flags = meta_flag,
+ .flags = meta_flag,
};
return iwl_send_cmd(priv, &cmd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 614ec7cc5b31..febcf76e1d41 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -446,9 +446,9 @@ int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id,
u16 len, const void *data);
int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
const void *data,
- int (*callback)(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
- struct sk_buff *skb));
+ void (*callback)(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb));
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 9faf0c2ff608..fbe177608bc7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -84,9 +84,11 @@ struct iwl_debugfs {
struct dentry *file_status;
struct dentry *file_interrupt;
struct dentry *file_qos;
+ struct dentry *file_thermal_throttling;
#ifdef CONFIG_IWLWIFI_LEDS
struct dentry *file_led;
#endif
+ struct dentry *file_disable_ht40;
} dbgfs_data_files;
struct dir_rf_files {
struct dentry *file_disable_sensitivity;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 0ab3463aa07e..7707a2655994 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -618,6 +618,84 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
}
#endif
+static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+ struct iwl_tt_restriction *restriction;
+ char buf[100];
+ int pos = 0;
+ const size_t bufsz = sizeof(buf);
+ ssize_t ret;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Thermal Throttling Mode: %s\n",
+ (priv->power_data.adv_tt)
+ ? "Advance" : "Legacy");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Thermal Throttling State: %d\n",
+ tt->state);
+ if (priv->power_data.adv_tt) {
+ restriction = tt->restriction + tt->state;
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Tx mode: %d\n",
+ restriction->tx_stream);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Rx mode: %d\n",
+ restriction->rx_stream);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "HT mode: %d\n",
+ restriction->is_ht);
+ }
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ char buf[8];
+ int buf_size;
+ int ht40;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ if (sscanf(buf, "%d", &ht40) != 1)
+ return -EFAULT;
+ if (!iwl_is_associated(priv))
+ priv->disable_ht40 = ht40 ? true : false;
+ else {
+ IWL_ERR(priv, "Sta associated with AP - "
+ "Change to 40MHz channel support is not allowed\n");
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ char buf[100];
+ int pos = 0;
+ const size_t bufsz = sizeof(buf);
+ ssize_t ret;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "11n 40MHz Mode: %s\n",
+ priv->disable_ht40 ? "Disabled" : "Enabled");
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ return ret;
+}
+
DEBUGFS_READ_WRITE_FILE_OPS(sram);
DEBUGFS_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(nvm);
@@ -631,6 +709,8 @@ DEBUGFS_READ_FILE_OPS(qos);
#ifdef CONFIG_IWLWIFI_LEDS
DEBUGFS_READ_FILE_OPS(led);
#endif
+DEBUGFS_READ_FILE_OPS(thermal_throttling);
+DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
/*
* Create the debugfs files and directories
@@ -671,6 +751,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
#ifdef CONFIG_IWLWIFI_LEDS
DEBUGFS_ADD_FILE(led, data);
#endif
+ DEBUGFS_ADD_FILE(thermal_throttling, data);
+ DEBUGFS_ADD_FILE(disable_ht40, data);
DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
&priv->disable_chain_noise_cal);
@@ -709,6 +791,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
#ifdef CONFIG_IWLWIFI_LEDS
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
#endif
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
DEBUGFS_REMOVE(priv->dbgfs->dir_data);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 0751891f4ab7..0ee3ad245697 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -63,6 +63,8 @@ extern struct iwl_cfg iwl6050_2agn_cfg;
extern struct iwl_cfg iwl6050_3agn_cfg;
extern struct iwl_cfg iwl1000_bgn_cfg;
+struct iwl_tx_queue;
+
/* shared structures from iwl-5000.c */
extern struct iwl_mod_params iwl50_mod_params;
extern struct iwl_ops iwl5000_ops;
@@ -79,9 +81,37 @@ extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
__le32 *tx_flags);
extern int iwl5000_calc_rssi(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp);
+extern int iwl5000_apm_init(struct iwl_priv *priv);
+extern void iwl5000_apm_stop(struct iwl_priv *priv);
+extern int iwl5000_apm_reset(struct iwl_priv *priv);
+extern void iwl5000_nic_config(struct iwl_priv *priv);
+extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv);
+extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
+ size_t offset);
+extern void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq,
+ u16 byte_cnt);
+extern void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq);
+extern int iwl5000_load_ucode(struct iwl_priv *priv);
+extern void iwl5000_init_alive_start(struct iwl_priv *priv);
+extern int iwl5000_alive_notify(struct iwl_priv *priv);
+extern int iwl5000_hw_set_hw_params(struct iwl_priv *priv);
+extern int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
+ int tx_fifo, int sta_id, int tid, u16 ssn_idx);
+extern int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
+ u16 ssn_idx, u8 tx_fifo);
+extern void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask);
+extern void iwl5000_setup_deferred_work(struct iwl_priv *priv);
+extern void iwl5000_rx_handler_setup(struct iwl_priv *priv);
+extern int iwl5000_hw_valid_rtc_data_addr(u32 addr);
+extern int iwl5000_send_tx_power(struct iwl_priv *priv);
+extern void iwl5000_temperature(struct iwl_priv *priv);
/* CT-KILL constants */
-#define CT_KILL_THRESHOLD 110 /* in Celsius */
+#define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */
+#define CT_KILL_THRESHOLD 114 /* in Celsius */
+#define CT_KILL_EXIT_THRESHOLD 95 /* in Celsius */
/* Default noise level to report when noise measurement is not available.
* This may be because we're:
@@ -120,6 +150,31 @@ struct iwl_rx_mem_buffer {
struct list_head list;
};
+/* defined below */
+struct iwl_device_cmd;
+
+struct iwl_cmd_meta {
+ /* only for SYNC commands, iff the reply skb is wanted */
+ struct iwl_host_cmd *source;
+ /*
+ * only for ASYNC commands
+ * (which is somewhat stupid -- look at iwl-sta.c for instance
+ * which duplicates a bunch of code because the callback isn't
+ * invoked for SYNC commands, if it were and its result passed
+ * through it would be simpler...)
+ */
+ void (*callback)(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb);
+
+ /* The CMD_SIZE_HUGE flag bit indicates that the command
+ * structure is stored at the end of the shared queue memory. */
+ u32 flags;
+
+ DECLARE_PCI_UNMAP_ADDR(mapping)
+ DECLARE_PCI_UNMAP_LEN(len)
+};
+
/*
* Generic queue structure
*
@@ -147,7 +202,8 @@ struct iwl_tx_info {
* struct iwl_tx_queue - Tx Queue for DMA
* @q: generic Rx/Tx queue descriptor
* @bd: base of circular buffer of TFDs
- * @cmd: array of command/Tx buffers
+ * @cmd: array of command/TX buffer pointers
+ * @meta: array of meta data for each command/tx buffer
* @dma_addr_cmd: physical address of cmd/tx buffer array
* @txb: array of per-TFD driver data
* @need_update: indicates need to update read/write index
@@ -162,7 +218,8 @@ struct iwl_tx_info {
struct iwl_tx_queue {
struct iwl_queue q;
void *tfds;
- struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS];
+ struct iwl_device_cmd **cmd;
+ struct iwl_cmd_meta *meta;
struct iwl_tx_info *txb;
u8 need_update;
u8 sched_retry;
@@ -299,35 +356,16 @@ enum {
CMD_WANT_SKB = (1 << 2),
};
-struct iwl_cmd;
-struct iwl_priv;
-
-struct iwl_cmd_meta {
- struct iwl_cmd_meta *source;
- union {
- struct sk_buff *skb;
- int (*callback)(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb);
- } __attribute__ ((packed)) u;
-
- /* The CMD_SIZE_HUGE flag bit indicates that the command
- * structure is stored at the end of the shared queue memory. */
- u32 flags;
- DECLARE_PCI_UNMAP_ADDR(mapping)
- DECLARE_PCI_UNMAP_LEN(len)
-} __attribute__ ((packed));
-
#define IWL_CMD_MAX_PAYLOAD 320
/**
- * struct iwl_cmd
+ * struct iwl_device_cmd
*
* For allocation of the command and tx queues, this establishes the overall
* size of the largest command we send to uCode, except for a scan command
* (which is relatively huge; space is allocated separately).
*/
-struct iwl_cmd {
- struct iwl_cmd_meta meta; /* driver data */
+struct iwl_device_cmd {
struct iwl_cmd_header hdr; /* uCode API */
union {
u32 flags;
@@ -339,17 +377,20 @@ struct iwl_cmd {
} __attribute__ ((packed)) cmd;
} __attribute__ ((packed));
+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
+
struct iwl_host_cmd {
- u8 id;
- u16 len;
- struct iwl_cmd_meta meta;
const void *data;
+ struct sk_buff *reply_skb;
+ void (*callback)(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb);
+ u32 flags;
+ u16 len;
+ u8 id;
};
-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_cmd) - \
- sizeof(struct iwl_cmd_meta))
-
/*
* RX related structures and functions
*/
@@ -450,8 +491,16 @@ union iwl_ht_rate_supp {
};
#define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3)
-#define CFG_HT_MPDU_DENSITY_2USEC (0x5)
-#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_2USEC
+
+/*
+ * Maximal MPDU density for TX aggregation
+ * 4 - 2us density
+ * 5 - 4us density
+ * 6 - 8us density
+ * 7 - 16us density
+ */
+#define CFG_HT_MPDU_DENSITY_4USEC (0x5)
+#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC
struct iwl_ht_info {
/* self configuration data */
@@ -630,6 +679,8 @@ struct iwl_hw_params {
u32 max_data_size;
u32 max_bsm_size;
u32 ct_kill_threshold; /* value in hw-dependent units */
+ u32 ct_kill_exit_threshold; /* value in hw-dependent units */
+ /* for 1000, 6000 series and up */
u32 calib_init_cfg;
const struct iwl_sensitivity_ranges *sens;
};
@@ -1113,6 +1164,7 @@ struct iwl_priv {
/* debugging info */
u32 framecnt_to_us;
atomic_t restrict_refcnt;
+ bool disable_ht40;
#ifdef CONFIG_IWLWIFI_DEBUGFS
/* debugfs */
struct iwl_debugfs *dbgfs;
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 17d61ac8ed61..b82ad15d5189 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -103,22 +103,23 @@ EXPORT_SYMBOL(get_cmd_string);
#define HOST_COMPLETE_TIMEOUT (HZ / 2)
-static int iwl_generic_cmd_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb)
+static void iwl_generic_cmd_callback(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb)
{
struct iwl_rx_packet *pkt = NULL;
if (!skb) {
IWL_ERR(priv, "Error: Response NULL in %s.\n",
get_cmd_string(cmd->hdr.cmd));
- return 1;
+ return;
}
pkt = (struct iwl_rx_packet *)skb->data;
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
- return 1;
+ return;
}
#ifdef CONFIG_IWLWIFI_DEBUG
@@ -127,29 +128,26 @@ static int iwl_generic_cmd_callback(struct iwl_priv *priv,
case SENSITIVITY_CMD:
IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n",
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
- break;
+ break;
default:
IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n",
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
}
#endif
-
- /* Let iwl_tx_complete free the response skb */
- return 1;
}
static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
int ret;
- BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
+ BUG_ON(!(cmd->flags & CMD_ASYNC));
/* An asynchronous command can not expect an SKB to be set. */
- BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
+ BUG_ON(cmd->flags & CMD_WANT_SKB);
/* Assign a generic callback if one is not provided */
- if (!cmd->meta.u.callback)
- cmd->meta.u.callback = iwl_generic_cmd_callback;
+ if (!cmd->callback)
+ cmd->callback = iwl_generic_cmd_callback;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EBUSY;
@@ -168,10 +166,10 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
int cmd_idx;
int ret;
- BUG_ON(cmd->meta.flags & CMD_ASYNC);
+ BUG_ON(cmd->flags & CMD_ASYNC);
/* A synchronous command can not have a callback set. */
- BUG_ON(cmd->meta.u.callback != NULL);
+ BUG_ON(cmd->callback);
if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
IWL_ERR(priv,
@@ -183,9 +181,6 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
set_bit(STATUS_HCMD_ACTIVE, &priv->status);
- if (cmd->meta.flags & CMD_WANT_SKB)
- cmd->meta.source = &cmd->meta;
-
cmd_idx = iwl_enqueue_hcmd(priv, cmd);
if (cmd_idx < 0) {
ret = cmd_idx;
@@ -222,7 +217,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
ret = -EIO;
goto fail;
}
- if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
+ if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_skb) {
IWL_ERR(priv, "Error: Response NULL in '%s'\n",
get_cmd_string(cmd->id));
ret = -EIO;
@@ -233,20 +228,20 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
goto out;
cancel:
- if (cmd->meta.flags & CMD_WANT_SKB) {
- struct iwl_cmd *qcmd;
-
- /* Cancel the CMD_WANT_SKB flag for the cmd in the
+ if (cmd->flags & CMD_WANT_SKB) {
+ /*
+ * Cancel the CMD_WANT_SKB flag for the cmd in the
* TX cmd queue. Otherwise in case the cmd comes
* in later, it will possibly set an invalid
- * address (cmd->meta.source). */
- qcmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
- qcmd->meta.flags &= ~CMD_WANT_SKB;
+ * address (cmd->meta.source).
+ */
+ priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_idx].flags &=
+ ~CMD_WANT_SKB;
}
fail:
- if (cmd->meta.u.skb) {
- dev_kfree_skb_any(cmd->meta.u.skb);
- cmd->meta.u.skb = NULL;
+ if (cmd->reply_skb) {
+ dev_kfree_skb_any(cmd->reply_skb);
+ cmd->reply_skb = NULL;
}
out:
clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
@@ -256,7 +251,7 @@ EXPORT_SYMBOL(iwl_send_cmd_sync);
int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
- if (cmd->meta.flags & CMD_ASYNC)
+ if (cmd->flags & CMD_ASYNC)
return iwl_send_cmd_async(priv, cmd);
return iwl_send_cmd_sync(priv, cmd);
@@ -277,9 +272,9 @@ EXPORT_SYMBOL(iwl_send_cmd_pdu);
int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
u8 id, u16 len, const void *data,
- int (*callback)(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
- struct sk_buff *skb))
+ void (*callback)(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb))
{
struct iwl_host_cmd cmd = {
.id = id,
@@ -287,8 +282,8 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
.data = data,
};
- cmd.meta.flags |= CMD_ASYNC;
- cmd.meta.u.callback = callback;
+ cmd.flags |= CMD_ASYNC;
+ cmd.callback = callback;
return iwl_send_cmd_async(priv, &cmd);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 8c8115293b3c..7cce8f85bcc6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -91,8 +91,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
.id = REPLY_LEDS_CMD,
.len = sizeof(struct iwl_led_cmd),
.data = led_cmd,
- .meta.flags = CMD_ASYNC,
- .meta.u.callback = NULL,
+ .flags = CMD_ASYNC,
+ .callback = NULL,
};
u32 reg;
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index f2ea3f05f6e1..00937b3ee8ec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -36,6 +36,7 @@
#include "iwl-eeprom.h"
#include "iwl-dev.h"
#include "iwl-core.h"
+#include "iwl-io.h"
#include "iwl-commands.h"
#include "iwl-debug.h"
#include "iwl-power.h"
@@ -97,6 +98,45 @@ static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
};
+/* default Thermal Throttling transaction table
+ * Current state | Throttling Down | Throttling Up
+ *=============================================================================
+ * Condition Nxt State Condition Nxt State Condition Nxt State
+ *-----------------------------------------------------------------------------
+ * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A
+ * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0
+ * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1
+ * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
+ *=============================================================================
+ */
+static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
+ {IWL_TI_1, 105, CT_KILL_THRESHOLD},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
+ {IWL_TI_2, 110, CT_KILL_THRESHOLD},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
+ {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
+ {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
+};
+
+/* Advance Thermal Throttling default restriction table */
+static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
+ {IWL_TX_MULTI, true, IWL_RX_MULTI},
+ {IWL_TX_SINGLE, true, IWL_RX_MULTI},
+ {IWL_TX_SINGLE, false, IWL_RX_SINGLE},
+ {IWL_TX_NONE, false, IWL_RX_NONE}
+};
/* set card power command */
static int iwl_set_power(struct iwl_priv *priv, void *cmd)
@@ -211,6 +251,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
{
struct iwl_power_mgr *setting = &(priv->power_data);
int ret = 0;
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
u16 uninitialized_var(final_mode);
bool update_chains;
@@ -223,6 +264,10 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
if (setting->power_disabled)
final_mode = IWL_POWER_MODE_CAM;
+ if (tt->state >= IWL_TI_1) {
+ /* TT power setting overwrite user & system power setting */
+ final_mode = tt->tt_power_mode;
+ }
if (iwl_is_ready_rf(priv) &&
((setting->power_mode != final_mode) || force)) {
struct iwl_powertable_cmd cmd;
@@ -267,6 +312,487 @@ int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
}
EXPORT_SYMBOL(iwl_power_set_user_mode);
+bool iwl_ht_enabled(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+ struct iwl_tt_restriction *restriction;
+
+ if (!priv->power_data.adv_tt)
+ return true;
+ restriction = tt->restriction + tt->state;
+ return restriction->is_ht;
+}
+EXPORT_SYMBOL(iwl_ht_enabled);
+
+u8 iwl_tx_ant_restriction(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+ struct iwl_tt_restriction *restriction;
+
+ if (!priv->power_data.adv_tt)
+ return IWL_TX_MULTI;
+ restriction = tt->restriction + tt->state;
+ return restriction->tx_stream;
+}
+EXPORT_SYMBOL(iwl_tx_ant_restriction);
+
+u8 iwl_rx_ant_restriction(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+ struct iwl_tt_restriction *restriction;
+
+ if (!priv->power_data.adv_tt)
+ return IWL_RX_MULTI;
+ restriction = tt->restriction + tt->state;
+ return restriction->rx_stream;
+}
+EXPORT_SYMBOL(iwl_rx_ant_restriction);
+
+#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
+
+/*
+ * toggle the bit to wake up uCode and check the temperature
+ * if the temperature is below CT, uCode will stay awake and send card
+ * state notification with CT_KILL bit clear to inform Thermal Throttling
+ * Management to change state. Otherwise, uCode will go back to sleep
+ * without doing anything, driver should continue the 5 seconds timer
+ * to wake up uCode for temperature check until temperature drop below CT
+ */
+static void iwl_tt_check_exit_ct_kill(unsigned long data)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)data;
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+ unsigned long flags;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if (tt->state == IWL_TI_CT_KILL) {
+ if (priv->power_data.ct_kill_toggle) {
+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+ priv->power_data.ct_kill_toggle = false;
+ } else {
+ iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+ priv->power_data.ct_kill_toggle = true;
+ }
+ iwl_read32(priv, CSR_UCODE_DRV_GP1);
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ if (!iwl_grab_nic_access(priv))
+ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+
+ /* Reschedule the ct_kill timer to occur in
+ * CT_KILL_EXIT_DURATION seconds to ensure we get a
+ * thermal update */
+ mod_timer(&priv->power_data.ct_kill_exit_tm, jiffies +
+ CT_KILL_EXIT_DURATION * HZ);
+ }
+}
+
+static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
+ bool stop)
+{
+ if (stop) {
+ IWL_DEBUG_POWER(priv, "Stop all queues\n");
+ if (priv->mac80211_registered)
+ ieee80211_stop_queues(priv->hw);
+ IWL_DEBUG_POWER(priv,
+ "Schedule 5 seconds CT_KILL Timer\n");
+ mod_timer(&priv->power_data.ct_kill_exit_tm, jiffies +
+ CT_KILL_EXIT_DURATION * HZ);
+ } else {
+ IWL_DEBUG_POWER(priv, "Wake all queues\n");
+ if (priv->mac80211_registered)
+ ieee80211_wake_queues(priv->hw);
+ }
+}
+
+#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY)
+#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100)
+#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90)
+
+/*
+ * Legacy thermal throttling
+ * 1) Avoid NIC destruction due to high temperatures
+ * Chip will identify dangerously high temperatures that can
+ * harm the device and will power down
+ * 2) Avoid the NIC power down due to high temperature
+ * Throttle early enough to lower the power consumption before
+ * drastic steps are needed
+ */
+static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
+{
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+ enum iwl_tt_state new_state;
+ struct iwl_power_mgr *setting = &priv->power_data;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if ((tt->tt_previous_temp) &&
+ (temp > tt->tt_previous_temp) &&
+ ((temp - tt->tt_previous_temp) >
+ IWL_TT_INCREASE_MARGIN)) {
+ IWL_DEBUG_POWER(priv,
+ "Temperature increase %d degree Celsius\n",
+ (temp - tt->tt_previous_temp));
+ }
+#endif
+ /* in Celsius */
+ if (temp >= IWL_MINIMAL_POWER_THRESHOLD)
+ new_state = IWL_TI_CT_KILL;
+ else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)
+ new_state = IWL_TI_2;
+ else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)
+ new_state = IWL_TI_1;
+ else
+ new_state = IWL_TI_0;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ tt->tt_previous_temp = temp;
+#endif
+ if (tt->state != new_state) {
+ if (tt->state == IWL_TI_0) {
+ tt->sys_power_mode = setting->power_mode;
+ IWL_DEBUG_POWER(priv, "current power mode: %u\n",
+ setting->power_mode);
+ }
+ switch (new_state) {
+ case IWL_TI_0:
+ /* when system ready to go back to IWL_TI_0 state
+ * using system power mode instead of TT power mode
+ * revert back to the orginal power mode which was saved
+ * before enter Thermal Throttling state
+ * update priv->power_data.user_power_setting to the
+ * required power mode to make sure
+ * iwl_power_update_mode() will update power correctly.
+ */
+ priv->power_data.user_power_setting =
+ tt->sys_power_mode;
+ tt->tt_power_mode = tt->sys_power_mode;
+ break;
+ case IWL_TI_1:
+ tt->tt_power_mode = IWL_POWER_INDEX_3;
+ break;
+ case IWL_TI_2:
+ tt->tt_power_mode = IWL_POWER_INDEX_4;
+ break;
+ default:
+ tt->tt_power_mode = IWL_POWER_INDEX_5;
+ break;
+ }
+ if (iwl_power_update_mode(priv, true)) {
+ /* TT state not updated
+ * try again during next temperature read
+ */
+ IWL_ERR(priv, "Cannot update power mode, "
+ "TT state not updated\n");
+ } else {
+ if (new_state == IWL_TI_CT_KILL)
+ iwl_perform_ct_kill_task(priv, true);
+ else if (tt->state == IWL_TI_CT_KILL &&
+ new_state != IWL_TI_CT_KILL)
+ iwl_perform_ct_kill_task(priv, false);
+ tt->state = new_state;
+ IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
+ tt->state);
+ IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
+ tt->tt_power_mode);
+ }
+ }
+}
+
+/*
+ * Advance thermal throttling
+ * 1) Avoid NIC destruction due to high temperatures
+ * Chip will identify dangerously high temperatures that can
+ * harm the device and will power down
+ * 2) Avoid the NIC power down due to high temperature
+ * Throttle early enough to lower the power consumption before
+ * drastic steps are needed
+ * Actions include relaxing the power down sleep thresholds and
+ * decreasing the number of TX streams
+ * 3) Avoid throughput performance impact as much as possible
+ *
+ *=============================================================================
+ * Condition Nxt State Condition Nxt State Condition Nxt State
+ *-----------------------------------------------------------------------------
+ * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A
+ * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0
+ * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1
+ * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
+ *=============================================================================
+ */
+static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
+{
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+ int i;
+ bool changed = false;
+ enum iwl_tt_state old_state;
+ struct iwl_tt_trans *transaction;
+
+ old_state = tt->state;
+ for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) {
+ /* based on the current TT state,
+ * find the curresponding transaction table
+ * each table has (IWL_TI_STATE_MAX - 1) entries
+ * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1))
+ * will advance to the correct table.
+ * then based on the current temperature
+ * find the next state need to transaction to
+ * go through all the possible (IWL_TI_STATE_MAX - 1) entries
+ * in the current table to see if transaction is needed
+ */
+ transaction = tt->transaction +
+ ((old_state * (IWL_TI_STATE_MAX - 1)) + i);
+ if (temp >= transaction->tt_low &&
+ temp <= transaction->tt_high) {
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if ((tt->tt_previous_temp) &&
+ (temp > tt->tt_previous_temp) &&
+ ((temp - tt->tt_previous_temp) >
+ IWL_TT_INCREASE_MARGIN)) {
+ IWL_DEBUG_POWER(priv,
+ "Temperature increase %d "
+ "degree Celsius\n",
+ (temp - tt->tt_previous_temp));
+ }
+ tt->tt_previous_temp = temp;
+#endif
+ if (old_state !=
+ transaction->next_state) {
+ changed = true;
+ tt->state =
+ transaction->next_state;
+ }
+ break;
+ }
+ }
+ if (changed) {
+ struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+ struct iwl_power_mgr *setting = &priv->power_data;
+
+ if (tt->state >= IWL_TI_1) {
+ /* if switching from IWL_TI_0 to other TT state
+ * save previous power setting in tt->sys_power_mode */
+ if (old_state == IWL_TI_0)
+ tt->sys_power_mode = setting->power_mode;
+ /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
+ tt->tt_power_mode = IWL_POWER_INDEX_5;
+ if (!iwl_ht_enabled(priv))
+ /* disable HT */
+ rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
+ RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
+ RXON_FLG_FAT_PROT_MSK |
+ RXON_FLG_HT_PROT_MSK);
+ else {
+ /* check HT capability and set
+ * according to the system HT capability
+ * in case get disabled before */
+ iwl_set_rxon_ht(priv, &priv->current_ht_config);
+ }
+
+ } else {
+ /* restore system power setting */
+ /* the previous power mode was saved in
+ * tt->sys_power_mode when system move into
+ * Thermal Throttling state
+ * set power_data.user_power_setting to the previous
+ * system power mode to make sure power will get
+ * updated correctly
+ */
+ priv->power_data.user_power_setting =
+ tt->sys_power_mode;
+ tt->tt_power_mode = tt->sys_power_mode;
+ /* check HT capability and set
+ * according to the system HT capability
+ * in case get disabled before */
+ iwl_set_rxon_ht(priv, &priv->current_ht_config);
+ }
+ if (iwl_power_update_mode(priv, true)) {
+ /* TT state not updated
+ * try again during next temperature read
+ */
+ IWL_ERR(priv, "Cannot update power mode, "
+ "TT state not updated\n");
+ tt->state = old_state;
+ } else {
+ IWL_DEBUG_POWER(priv,
+ "Thermal Throttling to new state: %u\n",
+ tt->state);
+ if (old_state != IWL_TI_CT_KILL &&
+ tt->state == IWL_TI_CT_KILL) {
+ IWL_DEBUG_POWER(priv, "Enter IWL_TI_CT_KILL\n");
+ iwl_perform_ct_kill_task(priv, true);
+
+ } else if (old_state == IWL_TI_CT_KILL &&
+ tt->state != IWL_TI_CT_KILL) {
+ IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
+ iwl_perform_ct_kill_task(priv, false);
+ }
+ }
+ }
+}
+
+/* Card State Notification indicated reach critical temperature
+ * if PSP not enable, no Thermal Throttling function will be performed
+ * just set the GP1 bit to acknowledge the event
+ * otherwise, go into IWL_TI_CT_KILL state
+ * since Card State Notification will not provide any temperature reading
+ * for Legacy mode
+ * so just pass the CT_KILL temperature to iwl_legacy_tt_handler()
+ * for advance mode
+ * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
+ */
+void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if (tt->state != IWL_TI_CT_KILL) {
+ IWL_ERR(priv, "Device reached critical temperature "
+ "- ucode going to sleep!\n");
+ if (!priv->power_data.adv_tt)
+ iwl_legacy_tt_handler(priv,
+ IWL_MINIMAL_POWER_THRESHOLD);
+ else
+ iwl_advance_tt_handler(priv,
+ CT_KILL_THRESHOLD + 1);
+ }
+}
+EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
+
+/* Card State Notification indicated out of critical temperature
+ * since Card State Notification will not provide any temperature reading
+ * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature
+ * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state
+ */
+void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ /* stop ct_kill_exit_tm timer */
+ del_timer_sync(&priv->power_data.ct_kill_exit_tm);
+
+ if (tt->state == IWL_TI_CT_KILL) {
+ IWL_ERR(priv,
+ "Device temperature below critical"
+ "- ucode awake!\n");
+ if (!priv->power_data.adv_tt)
+ iwl_legacy_tt_handler(priv,
+ IWL_REDUCED_PERFORMANCE_THRESHOLD_2);
+ else
+ iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD);
+ }
+}
+EXPORT_SYMBOL(iwl_tt_exit_ct_kill);
+
+void iwl_tt_handler(struct iwl_priv *priv)
+{
+ s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
+ temp = KELVIN_TO_CELSIUS(priv->temperature);
+
+ if (!priv->power_data.adv_tt)
+ iwl_legacy_tt_handler(priv, temp);
+ else
+ iwl_advance_tt_handler(priv, temp);
+}
+EXPORT_SYMBOL(iwl_tt_handler);
+
+/* Thermal throttling initialization
+ * For advance thermal throttling:
+ * Initialize Thermal Index and temperature threshold table
+ * Initialize thermal throttling restriction table
+ */
+void iwl_tt_initialize(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+ struct iwl_power_mgr *setting = &priv->power_data;
+ int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
+ struct iwl_tt_trans *transaction;
+
+ IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling \n");
+
+ memset(tt, 0, sizeof(struct iwl_tt_mgmt));
+
+ tt->state = IWL_TI_0;
+ tt->sys_power_mode = setting->power_mode;
+ tt->tt_power_mode = tt->sys_power_mode;
+ init_timer(&priv->power_data.ct_kill_exit_tm);
+ priv->power_data.ct_kill_exit_tm.data = (unsigned long)priv;
+ priv->power_data.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill;
+ switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
+ case CSR_HW_REV_TYPE_6x00:
+ case CSR_HW_REV_TYPE_6x50:
+ IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
+ tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
+ IWL_TI_STATE_MAX, GFP_KERNEL);
+ tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
+ IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1),
+ GFP_KERNEL);
+ if (!tt->restriction || !tt->transaction) {
+ IWL_ERR(priv, "Fallback to Legacy Throttling\n");
+ priv->power_data.adv_tt = false;
+ kfree(tt->restriction);
+ tt->restriction = NULL;
+ kfree(tt->transaction);
+ tt->transaction = NULL;
+ } else {
+ transaction = tt->transaction +
+ (IWL_TI_0 * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_0[0], size);
+ transaction = tt->transaction +
+ (IWL_TI_1 * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_1[0], size);
+ transaction = tt->transaction +
+ (IWL_TI_2 * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_2[0], size);
+ transaction = tt->transaction +
+ (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_3[0], size);
+ size = sizeof(struct iwl_tt_restriction) *
+ IWL_TI_STATE_MAX;
+ memcpy(tt->restriction,
+ &restriction_range[0], size);
+ priv->power_data.adv_tt = true;
+ }
+ break;
+ default:
+ IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
+ priv->power_data.adv_tt = false;
+ break;
+ }
+}
+EXPORT_SYMBOL(iwl_tt_initialize);
+
+/* cleanup thermal throttling management related memory and timer */
+void iwl_tt_exit(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+
+ /* stop ct_kill_exit_tm timer if activated */
+ del_timer_sync(&priv->power_data.ct_kill_exit_tm);
+
+ if (priv->power_data.adv_tt) {
+ /* free advance thermal throttling memory */
+ kfree(tt->restriction);
+ tt->restriction = NULL;
+ kfree(tt->transaction);
+ tt->transaction = NULL;
+ }
+}
+EXPORT_SYMBOL(iwl_tt_exit);
+
/* initialize to default */
void iwl_power_initialize(struct iwl_priv *priv)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 37ba3bb7a25a..3d49b7a45b74 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -33,6 +33,84 @@
struct iwl_priv;
+#define IWL_ABSOLUTE_ZERO 0
+#define IWL_ABSOLUTE_MAX 0xFFFFFFFF
+#define IWL_TT_INCREASE_MARGIN 5
+
+/* Tx/Rx restrictions */
+#define IWL_TX_MULTI 0x02
+#define IWL_TX_SINGLE 0x01
+#define IWL_TX_NONE 0x00
+#define IWL_RX_MULTI 0x02
+#define IWL_RX_SINGLE 0x01
+#define IWL_RX_NONE 0x00
+
+/* Thermal Throttling State Machine states */
+enum iwl_tt_state {
+ IWL_TI_0, /* normal temperature, system power state */
+ IWL_TI_1, /* high temperature detect, low power state */
+ IWL_TI_2, /* higher temperature detected, lower power state */
+ IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */
+ IWL_TI_STATE_MAX
+};
+
+/**
+ * struct iwl_tt_restriction - Thermal Throttling restriction table used
+ * by advance thermal throttling management
+ * based on the current thermal throttling state, determine
+ * number of tx/rx streams; and the status of HT operation
+ * @tx_stream: number of tx stream allowed
+ * @is_ht: ht enable/disable
+ * @rx_stream: number of rx stream allowed
+ */
+struct iwl_tt_restriction {
+ u8 tx_stream;
+ bool is_ht;
+ u8 rx_stream;
+};
+
+/**
+ * struct iwl_tt_trans - Thermal Throttling transaction table; used by
+ * advance thermal throttling algorithm to determine next
+ * thermal state to go based on the current temperature
+ * @next_state: next thermal throttling mode
+ * @tt_low: low temperature threshold to change state
+ * @tt_high: high temperature threshold to change state
+ */
+struct iwl_tt_trans {
+ enum iwl_tt_state next_state;
+ u32 tt_low;
+ u32 tt_high;
+};
+
+/**
+ * struct iwl_tt_mgnt - Thermal Throttling Management structure
+ * @state: current Thermal Throttling state
+ * @tt_power_mode: Thermal Throttling power mode index
+ * being used to set power level when
+ * when thermal throttling state != IWL_TI_0
+ * the tt_power_mode should set to different
+ * power mode based on the current tt state
+ * @sys_power_mode: previous system power mode
+ * before transition into TT state
+ * @tt_previous_temperature: last measured temperature
+ * @iwl_tt_restriction: ptr to restriction tbl, used by advance
+ * thermal throttling to determine how many tx/rx streams
+ * should be used in tt state; and can HT be enabled or not
+ * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling
+ * state transaction
+ */
+struct iwl_tt_mgmt {
+ enum iwl_tt_state state;
+ u8 tt_power_mode;
+ u8 sys_power_mode;
+#ifdef CONFIG_IWLWIFI_DEBUG
+ s32 tt_previous_temp;
+#endif
+ struct iwl_tt_restriction *restriction;
+ struct iwl_tt_trans *transaction;
+};
+
enum {
IWL_POWER_MODE_CAM, /* Continuously Aware Mode, always on */
IWL_POWER_INDEX_1,
@@ -59,10 +137,25 @@ struct iwl_power_mgr {
u8 power_mode;
u8 user_power_setting; /* set by user through sysfs */
u8 power_disabled; /* set by mac80211's CONF_PS */
+ struct iwl_tt_mgmt tt; /* Thermal Throttling Management */
+ bool adv_tt; /* false: legacy mode */
+ /* true: advance mode */
+ bool ct_kill_toggle; /* use to toggle the CSR bit when
+ * checking uCode temperature
+ */
+ struct timer_list ct_kill_exit_tm;
};
int iwl_power_update_mode(struct iwl_priv *priv, bool force);
int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode);
+bool iwl_ht_enabled(struct iwl_priv *priv);
+u8 iwl_tx_ant_restriction(struct iwl_priv *priv);
+u8 iwl_rx_ant_restriction(struct iwl_priv *priv);
+void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
+void iwl_tt_exit_ct_kill(struct iwl_priv *priv);
+void iwl_tt_handler(struct iwl_priv *priv);
+void iwl_tt_initialize(struct iwl_priv *priv);
+void iwl_tt_exit(struct iwl_priv *priv);
void iwl_power_initialize(struct iwl_priv *priv);
#endif /* __iwl_power_setting_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 00398d973a07..c4c916df4a43 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -115,7 +115,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
struct iwl_rx_packet *res;
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_ABORT_CMD,
- .meta.flags = CMD_WANT_SKB,
+ .flags = CMD_WANT_SKB,
};
/* If there isn't a scan actively going on in the hardware
@@ -132,7 +132,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
return ret;
}
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->u.status != CAN_ABORT_STATUS) {
/* The scan abort will return 1 for success or
* 2 for "failure". A failure condition can be
@@ -146,7 +146,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
}
priv->alloc_rxb_skb--;
- dev_kfree_skb_any(cmd.meta.u.skb);
+ dev_kfree_skb_any(cmd.reply_skb);
return ret;
}
@@ -567,7 +567,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
.len = sizeof(struct iwl_scan_cmd),
- .meta.flags = CMD_SIZE_HUGE,
+ .flags = CMD_SIZE_HUGE,
};
struct iwl_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index cbe4e26d053f..79ea5cc2c89a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -97,8 +97,9 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
-static int iwl_add_sta_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb)
+static void iwl_add_sta_callback(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb)
{
struct iwl_rx_packet *res = NULL;
struct iwl_addsta_cmd *addsta =
@@ -107,14 +108,14 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
if (!skb) {
IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n");
- return 1;
+ return;
}
res = (struct iwl_rx_packet *)skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
res->hdr.flags);
- return 1;
+ return;
}
switch (res->u.add_sta.status) {
@@ -126,9 +127,6 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
res->u.add_sta.status);
break;
}
-
- /* We didn't cache the SKB; let the caller free it */
- return 1;
}
int iwl_send_add_sta(struct iwl_priv *priv,
@@ -139,14 +137,14 @@ int iwl_send_add_sta(struct iwl_priv *priv,
u8 data[sizeof(*sta)];
struct iwl_host_cmd cmd = {
.id = REPLY_ADD_STA,
- .meta.flags = flags,
+ .flags = flags,
.data = data,
};
if (flags & CMD_ASYNC)
- cmd.meta.u.callback = iwl_add_sta_callback;
+ cmd.callback = iwl_add_sta_callback;
else
- cmd.meta.flags |= CMD_WANT_SKB;
+ cmd.flags |= CMD_WANT_SKB;
cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
ret = iwl_send_cmd(priv, &cmd);
@@ -154,7 +152,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
if (ret || (flags & CMD_ASYNC))
return ret;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
res->hdr.flags);
@@ -175,7 +173,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
}
priv->alloc_rxb_skb--;
- dev_kfree_skb_any(cmd.meta.u.skb);
+ dev_kfree_skb_any(cmd.reply_skb);
return ret;
}
@@ -324,8 +322,9 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
-static int iwl_remove_sta_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb)
+static void iwl_remove_sta_callback(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb)
{
struct iwl_rx_packet *res = NULL;
struct iwl_rem_sta_cmd *rm_sta =
@@ -334,14 +333,14 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv,
if (!skb) {
IWL_ERR(priv, "Error: Response NULL in REPLY_REMOVE_STA.\n");
- return 1;
+ return;
}
res = (struct iwl_rx_packet *)skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
res->hdr.flags);
- return 1;
+ return;
}
switch (res->u.rem_sta.status) {
@@ -352,9 +351,6 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv,
IWL_ERR(priv, "REPLY_REMOVE_STA failed\n");
break;
}
-
- /* We didn't cache the SKB; let the caller free it */
- return 1;
}
static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
@@ -368,7 +364,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
struct iwl_host_cmd cmd = {
.id = REPLY_REMOVE_STA,
.len = sizeof(struct iwl_rem_sta_cmd),
- .meta.flags = flags,
+ .flags = flags,
.data = &rm_sta_cmd,
};
@@ -377,15 +373,15 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
memcpy(&rm_sta_cmd.addr, addr , ETH_ALEN);
if (flags & CMD_ASYNC)
- cmd.meta.u.callback = iwl_remove_sta_callback;
+ cmd.callback = iwl_remove_sta_callback;
else
- cmd.meta.flags |= CMD_WANT_SKB;
+ cmd.flags |= CMD_WANT_SKB;
ret = iwl_send_cmd(priv, &cmd);
if (ret || (flags & CMD_ASYNC))
return ret;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
res->hdr.flags);
@@ -406,7 +402,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
}
priv->alloc_rxb_skb--;
- dev_kfree_skb_any(cmd.meta.u.skb);
+ dev_kfree_skb_any(cmd.reply_skb);
return ret;
}
@@ -525,7 +521,7 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
struct iwl_host_cmd cmd = {
.id = REPLY_WEPKEY,
.data = wep_cmd,
- .meta.flags = CMD_ASYNC,
+ .flags = CMD_ASYNC,
};
memset(wep_cmd, 0, cmd_size +
@@ -930,7 +926,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
struct iwl_host_cmd cmd = {
.id = REPLY_TX_LINK_QUALITY_CMD,
.len = sizeof(struct iwl_link_quality_cmd),
- .meta.flags = flags,
+ .flags = flags,
.data = lq,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index c7100b9dcede..6bb9602f3477 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -141,7 +141,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
priv->cfg->ops->lib->txq_free_tfd(priv, txq);
- len = sizeof(struct iwl_cmd) * q->n_window;
+ len = sizeof(struct iwl_device_cmd) * q->n_window;
/* De-alloc array of command/tx buffers */
for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
@@ -156,6 +156,12 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
kfree(txq->txb);
txq->txb = NULL;
+ /* deallocate arrays */
+ kfree(txq->cmd);
+ kfree(txq->meta);
+ txq->cmd = NULL;
+ txq->meta = NULL;
+
/* 0-fill queue descriptor structure */
memset(txq, 0, sizeof(*txq));
}
@@ -179,7 +185,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
if (q->n_bd == 0)
return;
- len = sizeof(struct iwl_cmd) * q->n_window;
+ len = sizeof(struct iwl_device_cmd) * q->n_window;
len += IWL_MAX_SCAN_SIZE;
/* De-alloc array of command/tx buffers */
@@ -318,6 +324,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
{
int i, len;
int ret;
+ int actual_slots = slots_num;
/*
* Alloc buffer array for commands (Tx or other types of commands).
@@ -327,14 +334,22 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
* For normal Tx queues (all other queues), no super-size command
* space is needed.
*/
- len = sizeof(struct iwl_cmd);
- for (i = 0; i <= slots_num; i++) {
- if (i == slots_num) {
- if (txq_id == IWL_CMD_QUEUE_NUM)
- len += IWL_MAX_SCAN_SIZE;
- else
- continue;
- }
+ if (txq_id == IWL_CMD_QUEUE_NUM)
+ actual_slots++;
+
+ txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots,
+ GFP_KERNEL);
+ txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots,
+ GFP_KERNEL);
+
+ if (!txq->meta || !txq->cmd)
+ goto out_free_arrays;
+
+ len = sizeof(struct iwl_device_cmd);
+ for (i = 0; i < actual_slots; i++) {
+ /* only happens for cmd queue */
+ if (i == slots_num)
+ len += IWL_MAX_SCAN_SIZE;
txq->cmd[i] = kmalloc(len, GFP_KERNEL);
if (!txq->cmd[i])
@@ -364,15 +379,12 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
return 0;
err:
- for (i = 0; i < slots_num; i++) {
+ for (i = 0; i < actual_slots; i++)
kfree(txq->cmd[i]);
- txq->cmd[i] = NULL;
- }
+out_free_arrays:
+ kfree(txq->meta);
+ kfree(txq->cmd);
- if (txq_id == IWL_CMD_QUEUE_NUM) {
- kfree(txq->cmd[slots_num]);
- txq->cmd[slots_num] = NULL;
- }
return -ENOMEM;
}
EXPORT_SYMBOL(iwl_tx_queue_init);
@@ -673,7 +685,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_tx_queue *txq;
struct iwl_queue *q;
- struct iwl_cmd *out_cmd;
+ struct iwl_device_cmd *out_cmd;
+ struct iwl_cmd_meta *out_meta;
struct iwl_tx_cmd *tx_cmd;
int swq_id, txq_id;
dma_addr_t phys_addr;
@@ -767,6 +780,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Set up first empty entry in queue's array of Tx/cmd buffers */
out_cmd = txq->cmd[q->write_ptr];
+ out_meta = &txq->meta[q->write_ptr];
tx_cmd = &out_cmd->cmd.tx;
memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
@@ -829,8 +843,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
txcmd_phys = pci_map_single(priv->pci_dev,
&out_cmd->hdr, len,
PCI_DMA_BIDIRECTIONAL);
- pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
- pci_unmap_len_set(&out_cmd->meta, len, len);
+ pci_unmap_addr_set(out_meta, mapping, txcmd_phys);
+ pci_unmap_len_set(out_meta, len, len);
/* Add buffer containing Tx command and MAC(!) header to TFD's
* first entry */
priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
@@ -923,7 +937,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
struct iwl_queue *q = &txq->q;
- struct iwl_cmd *out_cmd;
+ struct iwl_device_cmd *out_cmd;
+ struct iwl_cmd_meta *out_meta;
dma_addr_t phys_addr;
unsigned long flags;
int len, ret;
@@ -937,25 +952,31 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
* the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
* we will need to increase the size of the TFD entries */
BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
- !(cmd->meta.flags & CMD_SIZE_HUGE));
+ !(cmd->flags & CMD_SIZE_HUGE));
if (iwl_is_rfkill(priv)) {
IWL_DEBUG_INFO(priv, "Not sending command - RF KILL\n");
return -EIO;
}
- if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
+ if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
IWL_ERR(priv, "No space for Tx\n");
return -ENOSPC;
}
spin_lock_irqsave(&priv->hcmd_lock, flags);
- idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
+ idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
out_cmd = txq->cmd[idx];
+ out_meta = &txq->meta[idx];
+
+ out_meta->flags = cmd->flags;
+ if (cmd->flags & CMD_WANT_SKB)
+ out_meta->source = cmd;
+ if (cmd->flags & CMD_ASYNC)
+ out_meta->callback = cmd->callback;
out_cmd->hdr.cmd = cmd->id;
- memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta));
memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
/* At this point, the out_cmd now has all of the incoming cmd
@@ -964,9 +985,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
out_cmd->hdr.flags = 0;
out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
INDEX_TO_SEQ(q->write_ptr));
- if (out_cmd->meta.flags & CMD_SIZE_HUGE)
+ if (cmd->flags & CMD_SIZE_HUGE)
out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
- len = sizeof(struct iwl_cmd) - sizeof(struct iwl_cmd_meta);
+ len = sizeof(struct iwl_device_cmd);
len += (idx == TFD_CMD_SLOTS) ? IWL_MAX_SCAN_SIZE : 0;
@@ -998,8 +1019,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
fix_size, PCI_DMA_BIDIRECTIONAL);
- pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
- pci_unmap_len_set(&out_cmd->meta, len, fix_size);
+ pci_unmap_addr_set(out_meta, mapping, phys_addr);
+ pci_unmap_len_set(out_meta, len, fix_size);
priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
phys_addr, fix_size, 1,
@@ -1068,8 +1089,8 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
}
pci_unmap_single(priv->pci_dev,
- pci_unmap_addr(&txq->cmd[cmd_idx]->meta, mapping),
- pci_unmap_len(&txq->cmd[cmd_idx]->meta, len),
+ pci_unmap_addr(&txq->meta[cmd_idx], mapping),
+ pci_unmap_len(&txq->meta[cmd_idx], len),
PCI_DMA_BIDIRECTIONAL);
for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
@@ -1100,7 +1121,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
int index = SEQ_TO_INDEX(sequence);
int cmd_index;
bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
- struct iwl_cmd *cmd;
+ struct iwl_device_cmd *cmd;
+ struct iwl_cmd_meta *meta;
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
@@ -1110,24 +1132,24 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
txq_id, sequence,
priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr,
priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) {
- iwl_print_hex_error(priv, rxb, 32);
+ iwl_print_hex_error(priv, pkt, 32);
return;
}
cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
+ meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index];
/* Input error checking is done when commands are added to queue. */
- if (cmd->meta.flags & CMD_WANT_SKB) {
- cmd->meta.source->u.skb = rxb->skb;
- rxb->skb = NULL;
- } else if (cmd->meta.u.callback &&
- !cmd->meta.u.callback(priv, cmd, rxb->skb))
+ if (meta->flags & CMD_WANT_SKB) {
+ meta->source->reply_skb = rxb->skb;
rxb->skb = NULL;
+ } else if (meta->callback)
+ meta->callback(priv, cmd, rxb->skb);
iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
- if (!(cmd->meta.flags & CMD_ASYNC)) {
+ if (!(meta->flags & CMD_ASYNC)) {
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
wake_up_interruptible(&priv->wait_command_queue);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 2cc7e30d7743..5ded8983b915 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -363,7 +363,7 @@ static void iwl3945_unset_hw_params(struct iwl_priv *priv)
static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
struct ieee80211_tx_info *info,
- struct iwl_cmd *cmd,
+ struct iwl_device_cmd *cmd,
struct sk_buff *skb_frag,
int sta_id)
{
@@ -403,7 +403,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
* handle build REPLY_TX command notification.
*/
static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
+ struct iwl_device_cmd *cmd,
struct ieee80211_tx_info *info,
struct ieee80211_hdr *hdr, u8 std_id)
{
@@ -476,7 +476,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
struct iwl3945_tx_cmd *tx;
struct iwl_tx_queue *txq = NULL;
struct iwl_queue *q = NULL;
- struct iwl_cmd *out_cmd = NULL;
+ struct iwl_device_cmd *out_cmd;
+ struct iwl_cmd_meta *out_meta;
dma_addr_t phys_addr;
dma_addr_t txcmd_phys;
int txq_id = skb_get_queue_mapping(skb);
@@ -565,6 +566,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Init first empty entry in queue's array of Tx/cmd buffers */
out_cmd = txq->cmd[idx];
+ out_meta = &txq->meta[idx];
tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
memset(tx, 0, sizeof(*tx));
@@ -642,8 +644,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
len, PCI_DMA_TODEVICE);
/* we do not map meta data ... so we can safely access address to
* provide to unmap command*/
- pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
- pci_unmap_len_set(&out_cmd->meta, len, len);
+ pci_unmap_addr_set(out_meta, mapping, txcmd_phys);
+ pci_unmap_len_set(out_meta, len, len);
/* Add buffer containing Tx command and MAC(!) header to TFD's
* first entry */
@@ -753,7 +755,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
struct iwl_host_cmd cmd = {
.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
.data = (void *)&spectrum,
- .meta.flags = CMD_WANT_SKB,
+ .flags = CMD_WANT_SKB,
};
u32 add_time = le64_to_cpu(params->start_time);
int rc;
@@ -794,7 +796,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
if (rc)
return rc;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
rc = -EIO;
@@ -817,7 +819,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
break;
}
- dev_kfree_skb_any(cmd.meta.u.skb);
+ dev_kfree_skb_any(cmd.reply_skb);
return rc;
}
@@ -2717,7 +2719,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
.len = sizeof(struct iwl3945_scan_cmd),
- .meta.flags = CMD_SIZE_HUGE,
+ .flags = CMD_SIZE_HUGE,
};
int rc = 0;
struct iwl3945_scan_cmd *scan;