2008-05-23 02:11:06

by Zhu Yi

[permalink] [raw]
Subject: [PATCH 00/51] iwlwifi driver 05/23 updates

Hi John,

Here are some iwlwifi drivers update. Please apply.

Thanks,
-yi

[PATCH] iwlwifi: changing irrelevant comment
[PATCH] iwlwifi: remove iwl4965_nic_start function
[PATCH] mac80211: separate Tx and Rx MCS when configuring HT
[PATCH] iwlwifi: filling Tx MCS set
[PATCH] iwlwifi: rename iwl4965_queue to iwl_queue
[PATCH] iwlwifi: rename iwl4965_tx_info to iwl_tx_info
[PATCH] iwlwifi: get_hw_cmd_size
[PATCH] iwlwifi: remove 4965 from iwl4965_tx_queue_update_write_ptr
[PATCH] iwlwifi: remove 4965 prefix from iwl4965_frame
[PATCH] iwlwifi: remove 4965 from iwl4965_rate_info
[PATCH] iwlwifi: move iwl_bcast_addr to iwlcore
[PATCH] iwlwifi: move more station managment into iwl-sta.c
[PATCH] iwlwifi: remove 4956 form iwl4965_tx_cmd
[PATCH] iwlwifi: refactor ieee80211_get_qos_ctrl
[PATCH] iwlwifi: move TX code into iwl-tx.c
[PATCH] iwlwifi: don't switch to SGI if not supported by AP
[PATCH] iwlwifi: clean up and bug fix for security
[PATCH] iwlwifi: rename and move Tx queue activation/deactivation
[PATCH] iwlwifi: add rx_handlers stub for iwl5000
[PATCH] iwlwifi: add ucode loaders for iwl5000
[PATCH] iwlwifi: add ucode init flow handling for iwl5000
[PATCH] iwlwifi: iwl5000 WiFi/WiMax coexistence
[PATCH] iwlwifi: remove 4965 remainings in iwl-eeprom.c file
[PATCH] iwlwifi: add debugfs to disable/enable run time calibration
[PATCH] iwlwifi: refactor pci prob flow
[PATCH] iwlwifi: trigger event log from debugfs
[PATCH] iwlwifi: move iwl_dump_nic_error_log to iwlcore module
[PATCH] iwlwifi: add RTC data address for iwl5000
[PATCH] iwlwifi: use uCode error and event tables pointer w.r.t loaded image
[PATCH] iwlwifi: increase max payload of iwl_cmd
[PATCH] iwlwifi: create drivers debugfs dir under wiphy->debugfsdir
[PATCH] iwlwifi: mark 4965 ucode types
[PATCH] iwlwifi: remove unused variable form __iwl4965_down
[PATCH] iwlwifi: remove notif_missed_beacons variable
[PATCH] iwlwifi: clean up alive_start routine
[PATCH] iwlwifi: remove 4965 from alive_resp structures
[PATCH] iwlwifi: setup correctly L1 L0S pi link values
[PATCH] iwlwifi: implement apm reset flow
[PATCH] iwlwifi: implement apm stop function
[PATCH] iwlwifi: refactor stop master function
[PATCH] iwlwifi: move txq_ctx_stop into iwl-tx.c
[PATCH] iwlwifi: move iwl_rxq_stop into iwl-rx.c
[PATCH] iwlwifi: add remove station functionality
[PATCH] iwlwifi: move add sta handler to iwl-sta.c
[PATCH] iwlwifi: move iwl_rx_missed_beacon_notif to iwl-rx.c
[PATCH] iwlwifi-5000: implement initial calibration for 5000
[PATCH] iwlwifi: activate status ready timeout only for run time ucode
[PATCH] iwlwifi: add iwl5000_tx_response structure
[PATCH] iwlwifi: move tx response common handlers to iwlcore
[PATCH] iwlwifi: impelemnt 5000 tx response path
[PATCH] iwlwifi: move 4965 tx response into iwl-4965.c


2008-05-23 02:11:23

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: clean up and bug fix for security

From: Emmanuel Grumbach <[email protected]>

This patch cleans up code in security.

1) uses the new pointer to ieee80211_key_conf passed with the tx_control.
2) resolves bug reported by Mirco Tischler (sends ADD_STA in ASYNC mode)
3) resolves bug reported by Volker Braun regarding dynamic WEP
4) drops a WEP packet which has been garbaged by firmware. This can
happen upon rekeying.

Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +-
drivers/net/wireless/iwlwifi/iwl-dev.h | 1 -
drivers/net/wireless/iwlwifi/iwl-sta.c | 25 +++++++---------
drivers/net/wireless/iwlwifi/iwl-sta.h | 3 ++
drivers/net/wireless/iwlwifi/iwl-tx.c | 41 ++++++++-------------------
drivers/net/wireless/iwlwifi/iwl4965-base.c | 3 +-
6 files changed, 29 insertions(+), 46 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 8f0852d..52c7eae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2389,6 +2389,7 @@ static int iwl4965_set_decrypted_flag(struct iwl_priv *priv,
RX_RES_STATUS_BAD_KEY_TTAK)
break;

+ case RX_RES_STATUS_SEC_TYPE_WEP:
if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
RX_RES_STATUS_BAD_ICV_MIC) {
/* bad ICV, the packet is destroyed since the
@@ -2396,7 +2397,6 @@ static int iwl4965_set_decrypted_flag(struct iwl_priv *priv,
IWL_DEBUG_RX("Packet destroyed\n");
return -1;
}
- case RX_RES_STATUS_SEC_TYPE_WEP:
case RX_RES_STATUS_SEC_TYPE_CCMP:
if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
RX_RES_STATUS_DECRYPT_OK) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 7a54682..305491f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -442,7 +442,6 @@ struct iwl_hw_key {
enum ieee80211_key_alg alg;
int keylen;
u8 keyidx;
- struct ieee80211_key_conf *conf;
u8 key[32];
};

diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index c8e468f..99ee1e1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -324,7 +324,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
unsigned long flags;

keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
- keyconf->hw_key_idx = keyconf->keyidx;
+ keyconf->hw_key_idx = HW_KEY_DEFAULT;
priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;

spin_lock_irqsave(&priv->sta_lock, flags);
@@ -354,7 +354,6 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
int ret;

keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
- keyconf->hw_key_idx = keyconf->keyidx;

key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
@@ -411,7 +410,6 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
key_flags |= STA_KEY_MULTICAST_MSK;

keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- keyconf->hw_key_idx = keyconf->keyidx;

spin_lock_irqsave(&priv->sta_lock, flags);
priv->stations[sta_id].keyinfo.alg = keyconf->alg;
@@ -449,12 +447,10 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,

keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
- keyconf->hw_key_idx = keyconf->keyidx;

spin_lock_irqsave(&priv->sta_lock, flags);

priv->stations[sta_id].keyinfo.alg = keyconf->alg;
- priv->stations[sta_id].keyinfo.conf = keyconf;
priv->stations[sta_id].keyinfo.keylen = 16;

if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
@@ -483,7 +479,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
u16 key_flags;
u8 keyidx;

- priv->key_mapping_key = 0;
+ priv->key_mapping_key--;

spin_lock_irqsave(&priv->sta_lock, flags);
key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
@@ -514,31 +510,32 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;

IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
- ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0);
+ ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
}
EXPORT_SYMBOL(iwl_remove_dynamic_key);

int iwl_set_dynamic_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *key, u8 sta_id)
+ struct ieee80211_key_conf *keyconf, u8 sta_id)
{
int ret;

- priv->key_mapping_key = 1;
+ priv->key_mapping_key++;
+ keyconf->hw_key_idx = HW_KEY_DYNAMIC;

- switch (key->alg) {
+ switch (keyconf->alg) {
case ALG_CCMP:
- ret = iwl_set_ccmp_dynamic_key_info(priv, key, sta_id);
+ ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
break;
case ALG_TKIP:
- ret = iwl_set_tkip_dynamic_key_info(priv, key, sta_id);
+ ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
break;
case ALG_WEP:
- ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id);
+ ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id);
break;
default:
- IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg);
+ IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
ret = -EINVAL;
}

diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index ee25643..b643546 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -29,6 +29,9 @@
#ifndef __iwl_sta_h__
#define __iwl_sta_h__

+#define HW_KEY_DYNAMIC 0
+#define HW_KEY_DEFAULT 1
+
int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty);
int iwl_remove_default_wep_key(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index a37ced5..f32cdda 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -639,16 +639,12 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
struct sk_buff *skb_frag,
int sta_id)
{
- struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
- struct iwl_wep_key *wepkey;
- int keyidx = 0;
+ struct ieee80211_key_conf *keyconf = ctl->hw_key;

- BUG_ON(ctl->hw_key->hw_key_idx > 3);
-
- switch (keyinfo->alg) {
+ switch (keyconf->alg) {
case ALG_CCMP:
tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
- memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
+ memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
if (ctl->flags & IEEE80211_TXCTL_AMPDU)
tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
@@ -656,39 +652,26 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,

case ALG_TKIP:
tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
- ieee80211_get_tkip_key(keyinfo->conf, skb_frag,
+ ieee80211_get_tkip_key(keyconf, skb_frag,
IEEE80211_TKIP_P2_KEY, tx_cmd->key);
IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n");
break;

case ALG_WEP:
- wepkey = &priv->wep_keys[ctl->hw_key->hw_key_idx];
- tx_cmd->sec_ctl = 0;
- if (priv->default_wep_key) {
- /* the WEP key was sent as static */
- keyidx = ctl->hw_key->hw_key_idx;
- memcpy(&tx_cmd->key[3], wepkey->key,
- wepkey->key_size);
- if (wepkey->key_size == WEP_KEY_LEN_128)
- tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
- } else {
- /* the WEP key was sent as dynamic */
- keyidx = keyinfo->keyidx;
- memcpy(&tx_cmd->key[3], keyinfo->key,
- keyinfo->keylen);
- if (keyinfo->keylen == WEP_KEY_LEN_128)
- tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
- }
-
tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP |
- (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
+ (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
+
+ if (keyconf->keylen == WEP_KEY_LEN_128)
+ tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+
+ memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);

IWL_DEBUG_TX("Configuring packet for WEP encryption "
- "with key %d\n", keyidx);
+ "with key %d\n", keyconf->keyidx);
break;

default:
- printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
+ printk(KERN_ERR "Unknown encode alg %d\n", keyconf->alg);
break;
}
}
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index a532a9e..40616db 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -4951,7 +4951,8 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (cmd == SET_KEY)
is_default_wep_key = !priv->key_mapping_key;
else
- is_default_wep_key = priv->default_wep_key;
+ is_default_wep_key =
+ (key->hw_key_idx == HW_KEY_DEFAULT);
}

switch (cmd) {
--
1.5.3.6


2008-05-23 02:11:55

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: implement apm stop function

From: Tomas Winkler <[email protected]>

This patch adds apm stop function for 4965 and 5000.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 19 ++++++++++++++++++-
drivers/net/wireless/iwlwifi/iwl-5000.c | 20 ++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-core.h | 1 +
3 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 639ad50..378fd83 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -646,6 +646,22 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
iwl_hw_txq_ctx_free(priv);
}

+static void iwl4965_apm_stop(struct iwl_priv *priv)
+{
+ unsigned long flags;
+
+ iwl4965_hw_nic_stop_master(priv);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+
+ udelay(10);
+
+ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
static int iwl4965_apm_reset(struct iwl_priv *priv)
{
int ret = 0;
@@ -662,6 +678,7 @@ static int iwl4965_apm_reset(struct iwl_priv *priv)
/* FIXME: put here L1A -L0S w/a */

iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
ret = iwl_poll_bit(priv, CSR_RESET,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25);
@@ -693,7 +710,6 @@ out:
spin_unlock_irqrestore(&priv->lock, flags);

return ret;
-
}

#define REG_RECALIB_PERIOD (60)
@@ -3629,6 +3645,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.apm_ops = {
.init = iwl4965_apm_init,
.reset = iwl4965_apm_reset,
+ .stop = iwl4965_apm_stop,
.config = iwl4965_nic_config,
.set_pwr_src = iwl4965_set_pwr_src,
},
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 10054bd..27cfe3c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -100,6 +100,25 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
return ret;
}

+/* FIXME: this is indentical to 4965 */
+static void iwl5000_apm_stop(struct iwl_priv *priv)
+{
+ unsigned long flags;
+
+ iwl4965_hw_nic_stop_master(priv);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+
+ udelay(10);
+
+ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+
static int iwl5000_apm_reset(struct iwl_priv *priv)
{
int ret = 0;
@@ -859,6 +878,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.apm_ops = {
.init = iwl5000_apm_init,
.reset = iwl5000_apm_reset,
+ .stop = iwl5000_apm_stop,
.config = iwl5000_nic_config,
.set_pwr_src = iwl4965_set_pwr_src,
},
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 70cc9d3..916e0a4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -125,6 +125,7 @@ struct iwl_lib_ops {
struct {
int (*init)(struct iwl_priv *priv);
int (*reset)(struct iwl_priv *priv);
+ void (*stop)(struct iwl_priv *priv);
void (*config)(struct iwl_priv *priv);
int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
} apm_ops;
--
1.5.3.6


2008-05-23 02:11:34

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: add debugfs to disable/enable run time calibration

From: Tomas Winkler <[email protected]>

This patch adds functionality to debugfs to enable or disable chain
noise or sensitivity calibrations.

Signed-off-by: Tomas Winkler <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-calib.c | 9 +++++++++
drivers/net/wireless/iwlwifi/iwl-calib.h | 4 +++-
drivers/net/wireless/iwlwifi/iwl-debug.h | 9 ++++++++-
drivers/net/wireless/iwlwifi/iwl-debugfs.c | 20 +++++++++++++++++++-
drivers/net/wireless/iwlwifi/iwl-dev.h | 6 +++++-
5 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index 1289d4c..beb9716 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -426,6 +426,9 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
struct iwl_sensitivity_data *data = NULL;
const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;

+ if (priv->disable_sens_cal)
+ return;
+
IWL_DEBUG_CALIB("Start iwl_init_sensitivity\n");

/* Clear driver's sensitivity algo data */
@@ -486,6 +489,9 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv,
unsigned long flags;
struct statistics_general_data statis;

+ if (priv->disable_sens_cal)
+ return;
+
data = &(priv->sensitivity_data);

if (!iwl_is_associated(priv)) {
@@ -608,6 +614,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
unsigned long flags;
struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general);

+ if (priv->disable_chain_noise_cal)
+ return;
+
data = &(priv->chain_noise_data);

/* Accumulate just the first 20 beacons after the first association,
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h
index 933b0b0..e690668 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.h
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.h
@@ -81,7 +81,9 @@ void iwl_init_sensitivity(struct iwl_priv *priv);

static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
{
- if (priv->cfg->ops->utils->chain_noise_reset)
+
+ if (!priv->disable_chain_noise_cal &&
+ priv->cfg->ops->utils->chain_noise_reset)
priv->cfg->ops->utils->chain_noise_reset(priv);
}
#else
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 2f24594..c3f8e90 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -45,13 +45,20 @@ struct iwl_debugfs {
const char *name;
struct dentry *dir_drv;
struct dentry *dir_data;
- struct dir_data_files{
+ struct dentry *dir_rf;
+ struct dir_data_files {
struct dentry *file_sram;
struct dentry *file_eeprom;
struct dentry *file_stations;
struct dentry *file_rx_statistics;
struct dentry *file_tx_statistics;
} dbgfs_data_files;
+ struct dir_rf_files {
+#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
+ struct dentry *file_disable_sensitivity;
+ struct dentry *file_disable_chain_noise;
+#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */
+ } dbgfs_rf_files;
u32 sram_offset;
u32 sram_len;
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index ad25806..f7ec200 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -55,6 +55,13 @@
goto err; \
} while (0)

+#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
+ dbgfs->dbgfs_##parent##_files.file_##name = \
+ debugfs_create_bool(#name, 0644, dbgfs->dir_##parent, ptr); \
+ if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name)) \
+ goto err; \
+} while (0)
+
#define DEBUGFS_REMOVE(name) do { \
debugfs_remove(name); \
name = NULL; \
@@ -344,12 +351,17 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
}

DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
+ DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
DEBUGFS_ADD_FILE(eeprom, data);
DEBUGFS_ADD_FILE(sram, data);
DEBUGFS_ADD_FILE(stations, data);
DEBUGFS_ADD_FILE(rx_statistics, data);
DEBUGFS_ADD_FILE(tx_statistics, data);
-
+#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
+ DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
+ DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
+ &priv->disable_chain_noise_cal);
+#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */
return 0;

err:
@@ -374,6 +386,11 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
DEBUGFS_REMOVE(priv->dbgfs->dir_data);
+#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
+#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */
+ DEBUGFS_REMOVE(priv->dbgfs->dir_rf);
DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
kfree(priv->dbgfs);
priv->dbgfs = NULL;
@@ -381,3 +398,4 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
EXPORT_SYMBOL(iwl_dbgfs_unregister);


+
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index b1ff0af..820542b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1212,9 +1212,13 @@ struct iwl_priv {
#endif /* CONFIG_IWLWIFI_DEBUG */

struct work_struct txpower_work;
+#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
+ u32 disable_sens_cal;
+ u32 disable_chain_noise_cal;
+#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */
#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
struct work_struct sensitivity_work;
-#endif
+#endif /* CONFIG_IWL4965_RUN_TIME_CALIB */
struct timer_list statistics_periodic;
}; /*iwl_priv */

--
1.5.3.6


2008-05-23 02:11:39

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: add RTC data address for iwl5000

From: Ron Rindjunsky <[email protected]>

This patch fills the valid_rtc_data_addr handler in iwl5000.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-5000.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 520c7ea..d6ffdee 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -768,6 +768,12 @@ static void iwl5000_rx_handler_setup(struct iwl_priv *priv)
{
}

+static int iwl5000_hw_valid_rtc_data_addr(u32 addr)
+{
+ return (addr >= RTC_DATA_LOWER_BOUND) &&
+ (addr < IWL50_RTC_DATA_UPPER_BOUND);
+}
+
static struct iwl_hcmd_ops iwl5000_hcmd = {
};

@@ -788,6 +794,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
.disable_tx_fifo = iwl5000_disable_tx_fifo,
.rx_handler_setup = iwl5000_rx_handler_setup,
+ .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,
--
1.5.3.6


2008-05-23 02:11:47

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: remove notif_missed_beacons variable

From: Tomas Winkler <[email protected]>

This patch removes notif_missed_beacons from priv since it was never
used. Missed beacons notification will have only meaning if roaming
will be implemented in mac80211.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-3945.h | 2 --
drivers/net/wireless/iwlwifi/iwl-dev.h | 2 --
drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 ---
drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 --
4 files changed, 0 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index 9fdc140..d100c38 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -836,8 +836,6 @@ struct iwl3945_priv {

u8 mac80211_registered;

- u32 notif_missed_beacons;
-
/* Rx'd packet timing information */
u32 last_beacon_time;
u64 last_tsf;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index b61c647..ea08cf9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1126,8 +1126,6 @@ struct iwl_priv {

u8 mac80211_registered;

- u32 notif_missed_beacons;
-
/* Rx'd packet timing information */
u32 last_beacon_time;
u64 last_tsf;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index b8fb8d8..3104f6a 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -5849,9 +5849,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
/* Configure the adapter for unassociated operation */
iwl3945_commit_rxon(priv);

- /* At this point, the NIC is initialized and operational */
- priv->notif_missed_beacons = 0;
-
iwl3945_reg_txpower_periodic(priv);

iwl3945_led_register(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index bf975cb..89dd890 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -3322,8 +3322,6 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
iwl4965_commit_rxon(priv);

/* At this point, the NIC is initialized and operational */
- priv->notif_missed_beacons = 0;
-
iwl4965_rf_kill_ct_config(priv);

iwl_leds_register(priv);
--
1.5.3.6


2008-05-23 02:11:45

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: mark 4965 ucode types

From: Tomas Winkler <[email protected]>

This patch marks 4965 ucode types.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index f848a5b..c92742c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -162,9 +162,10 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)

/* Tell bootstrap uCode where to find the "Initialize" uCode
* in host DRAM ... host DRAM physical address bits 35:4 for 4965.
- * NOTE: iwl4965_initialize_alive_start() will replace these values,
+ * NOTE: iwl_init_alive_start() will replace these values,
* after the "initialize" uCode has run, to point to
- * runtime/protocol instructions and backup data cache. */
+ * runtime/protocol instructions and backup data cache.
+ */
pinst = priv->ucode_init.p_addr >> 4;
pdata = priv->ucode_init_data.p_addr >> 4;
inst_len = priv->ucode_init.len;
@@ -220,6 +221,8 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)

iwl_release_nic_access(priv);

+ priv->ucode_type = UCODE_INIT;
+
return 0;
}

@@ -266,6 +269,8 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)

IWL_DEBUG_INFO("Runtime uCode pointers are set.\n");

+ priv->ucode_type = UCODE_RT;
+
return ret;
}

--
1.5.3.6


2008-05-23 02:11:08

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: changing irrelevant comment

From: Ron Rindjunsky <[email protected]>

This patch changes an old eeprom comment in probe flow.

Signed-off-by: Ron Rindjunsky <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 55ca752..d0f948d 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -6605,7 +6605,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
if (err)
goto out_iounmap;

- /* MAC Address location in EEPROM same for 3945/4965 */
+ /* extract MAC Address */
iwl_eeprom_get_mac(priv, priv->mac_addr);
IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
--
1.5.3.6


2008-05-23 02:11:12

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: remove 4965 prefix from iwl4965_frame

From: Tomas Winkler <[email protected]>

This patch removes 4965 from iwl4965_frame struct and handling functions.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +-
drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ++--
drivers/net/wireless/iwlwifi/iwl4965-base.c | 20 ++++++++++----------
3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 83876a0..922b0a1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2016,7 +2016,7 @@ int iwl4965_hw_get_temperature(struct iwl_priv *priv)
}

unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
- struct iwl4965_frame *frame, u8 rate)
+ struct iwl_frame *frame, u8 rate)
{
struct iwl4965_tx_beacon_cmd *tx_beacon_cmd;
unsigned int frame_size;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 9a842fd..60a8f06 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -262,7 +262,7 @@ enum iwl_pwr_src {
#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)

-struct iwl4965_frame {
+struct iwl_frame {
union {
struct ieee80211_hdr frame;
struct iwl4965_tx_beacon_cmd beacon;
@@ -696,7 +696,7 @@ extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
dma_addr_t addr, u16 len);
extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
- struct iwl4965_frame *frame, u8 rate);
+ struct iwl_frame *frame, u8 rate);
extern void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
struct iwl_cmd *cmd,
struct ieee80211_tx_control *ctrl,
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 0ad9558..1c45b6f 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -800,7 +800,7 @@ static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_fla
return iwl_send_cmd(priv, &cmd);
}

-static void iwl4965_clear_free_frames(struct iwl_priv *priv)
+static void iwl_clear_free_frames(struct iwl_priv *priv)
{
struct list_head *element;

@@ -810,7 +810,7 @@ static void iwl4965_clear_free_frames(struct iwl_priv *priv)
while (!list_empty(&priv->free_frames)) {
element = priv->free_frames.next;
list_del(element);
- kfree(list_entry(element, struct iwl4965_frame, list));
+ kfree(list_entry(element, struct iwl_frame, list));
priv->frames_count--;
}

@@ -821,9 +821,9 @@ static void iwl4965_clear_free_frames(struct iwl_priv *priv)
}
}

-static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl_priv *priv)
+static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
{
- struct iwl4965_frame *frame;
+ struct iwl_frame *frame;
struct list_head *element;
if (list_empty(&priv->free_frames)) {
frame = kzalloc(sizeof(*frame), GFP_KERNEL);
@@ -838,10 +838,10 @@ static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl_priv *priv)

element = priv->free_frames.next;
list_del(element);
- return list_entry(element, struct iwl4965_frame, list);
+ return list_entry(element, struct iwl_frame, list);
}

-static void iwl4965_free_frame(struct iwl_priv *priv, struct iwl4965_frame *frame)
+static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
{
memset(frame, 0, sizeof(*frame));
list_add(&frame->list, &priv->free_frames);
@@ -892,12 +892,12 @@ static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)

static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
{
- struct iwl4965_frame *frame;
+ struct iwl_frame *frame;
unsigned int frame_size;
int rc;
u8 rate;

- frame = iwl4965_get_free_frame(priv);
+ frame = iwl_get_free_frame(priv);

if (!frame) {
IWL_ERROR("Could not obtain free frame buffer for beacon "
@@ -912,7 +912,7 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
&frame->u.cmd[0]);

- iwl4965_free_frame(priv, frame);
+ iwl_free_frame(priv, frame);

return rc;
}
@@ -4355,7 +4355,7 @@ static void __iwl4965_down(struct iwl_priv *priv)
priv->ibss_beacon = NULL;

/* clear out any free frames */
- iwl4965_clear_free_frames(priv);
+ iwl_clear_free_frames(priv);
}

static void iwl4965_down(struct iwl_priv *priv)
--
1.5.3.6


2008-05-23 02:12:13

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: move 4965 tx response into iwl-4965.c

From: Tomas Winkler <[email protected]>

This patch moves 4965 tx repsone into iwl-4965.c.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 248 +++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl4965-base.c | 245 --------------------------
2 files changed, 248 insertions(+), 245 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index d657b43..03d449f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -3481,6 +3481,252 @@ static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)

return (u16)sizeof(struct iwl4965_addsta_cmd);
}
+
+#ifdef CONFIG_IWL4965_HT
+static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
+{
+ __le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status +
+ tx_resp->frame_count);
+ return le32_to_cpu(*scd_ssn) & MAX_SN;
+
+}
+
+/**
+ * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
+ */
+static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
+ struct iwl_ht_agg *agg,
+ struct iwl4965_tx_resp_agg *tx_resp,
+ u16 start_idx)
+{
+ u16 status;
+ struct agg_tx_status *frame_status = &tx_resp->status;
+ struct ieee80211_tx_status *tx_status = NULL;
+ struct ieee80211_hdr *hdr = NULL;
+ int i, sh;
+ int txq_id, idx;
+ u16 seq;
+
+ if (agg->wait_for_ba)
+ IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n");
+
+ agg->frame_count = tx_resp->frame_count;
+ agg->start_idx = start_idx;
+ agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+ agg->bitmap = 0;
+
+ /* # frames attempted by Tx command */
+ if (agg->frame_count == 1) {
+ /* Only one frame was attempted; no block-ack will arrive */
+ status = le16_to_cpu(frame_status[0].status);
+ seq = le16_to_cpu(frame_status[0].sequence);
+ idx = SEQ_TO_INDEX(seq);
+ txq_id = SEQ_TO_QUEUE(seq);
+
+ /* FIXME: code repetition */
+ IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
+ agg->frame_count, agg->start_idx, idx);
+
+ tx_status = &(priv->txq[txq_id].txb[idx].status);
+ tx_status->retry_count = tx_resp->failure_frame;
+ tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU;
+ tx_status->flags = iwl_is_tx_success(status)?
+ IEEE80211_TX_STATUS_ACK : 0;
+ iwl4965_hwrate_to_tx_control(priv,
+ le32_to_cpu(tx_resp->rate_n_flags),
+ &tx_status->control);
+ /* FIXME: code repetition end */
+
+ IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
+ status & 0xff, tx_resp->failure_frame);
+ IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n",
+ iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags));
+
+ agg->wait_for_ba = 0;
+ } else {
+ /* Two or more frames were attempted; expect block-ack */
+ u64 bitmap = 0;
+ int start = agg->start_idx;
+
+ /* Construct bit-map of pending frames within Tx window */
+ for (i = 0; i < agg->frame_count; i++) {
+ u16 sc;
+ status = le16_to_cpu(frame_status[i].status);
+ seq = le16_to_cpu(frame_status[i].sequence);
+ idx = SEQ_TO_INDEX(seq);
+ txq_id = SEQ_TO_QUEUE(seq);
+
+ if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
+ AGG_TX_STATE_ABORT_MSK))
+ continue;
+
+ IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n",
+ agg->frame_count, txq_id, idx);
+
+ hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
+
+ sc = le16_to_cpu(hdr->seq_ctrl);
+ if (idx != (SEQ_TO_SN(sc) & 0xff)) {
+ IWL_ERROR("BUG_ON idx doesn't match seq control"
+ " idx=%d, seq_idx=%d, seq=%d\n",
+ idx, SEQ_TO_SN(sc),
+ hdr->seq_ctrl);
+ return -1;
+ }
+
+ IWL_DEBUG_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n",
+ i, idx, SEQ_TO_SN(sc));
+
+ sh = idx - start;
+ if (sh > 64) {
+ sh = (start - idx) + 0xff;
+ bitmap = bitmap << sh;
+ sh = 0;
+ start = idx;
+ } else if (sh < -64)
+ sh = 0xff - (start - idx);
+ else if (sh < 0) {
+ sh = start - idx;
+ start = idx;
+ bitmap = bitmap << sh;
+ sh = 0;
+ }
+ bitmap |= (1 << sh);
+ IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n",
+ start, (u32)(bitmap & 0xFFFFFFFF));
+ }
+
+ agg->bitmap = bitmap;
+ agg->start_idx = start;
+ agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+ IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n",
+ agg->frame_count, agg->start_idx,
+ (unsigned long long)agg->bitmap);
+
+ if (bitmap)
+ agg->wait_for_ba = 1;
+ }
+ return 0;
+}
+#endif
+
+/**
+ * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
+ */
+static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+ int txq_id = SEQ_TO_QUEUE(sequence);
+ int index = SEQ_TO_INDEX(sequence);
+ struct iwl_tx_queue *txq = &priv->txq[txq_id];
+ struct ieee80211_tx_status *tx_status;
+ struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+ u32 status = le32_to_cpu(tx_resp->status);
+#ifdef CONFIG_IWL4965_HT
+ int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
+ u16 fc;
+ struct ieee80211_hdr *hdr;
+ u8 *qc = NULL;
+#endif
+
+ if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
+ IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
+ "is out of range [0-%d] %d %d\n", txq_id,
+ index, txq->q.n_bd, txq->q.write_ptr,
+ txq->q.read_ptr);
+ return;
+ }
+
+#ifdef CONFIG_IWL4965_HT
+ hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
+ fc = le16_to_cpu(hdr->frame_control);
+ if (ieee80211_is_qos_data(fc)) {
+ qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
+ tid = qc[0] & 0xf;
+ }
+
+ sta_id = iwl_get_ra_sta_id(priv, hdr);
+ if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
+ IWL_ERROR("Station not known\n");
+ return;
+ }
+
+ if (txq->sched_retry) {
+ const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
+ struct iwl_ht_agg *agg = NULL;
+
+ if (!qc)
+ return;
+
+ agg = &priv->stations[sta_id].tid[tid].agg;
+
+ iwl4965_tx_status_reply_tx(priv, agg,
+ (struct iwl4965_tx_resp_agg *)tx_resp, index);
+
+ if ((tx_resp->frame_count == 1) &&
+ !iwl_is_tx_success(status)) {
+ /* TODO: send BAR */
+ }
+
+ if (txq->q.read_ptr != (scd_ssn & 0xff)) {
+ int freed, ampdu_q;
+ index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
+ IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
+ "%d index %d\n", scd_ssn , index);
+ freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
+ priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+
+ if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
+ txq_id >= 0 && priv->mac80211_registered &&
+ agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
+ /* calculate mac80211 ampdu sw queue to wake */
+ ampdu_q = txq_id - IWL_BACK_QUEUE_FIRST_ID +
+ priv->hw->queues;
+ if (agg->state == IWL_AGG_OFF)
+ ieee80211_wake_queue(priv->hw, txq_id);
+ else
+ ieee80211_wake_queue(priv->hw, ampdu_q);
+ }
+ iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
+ }
+ } else {
+#endif /* CONFIG_IWL4965_HT */
+ tx_status = &(txq->txb[txq->q.read_ptr].status);
+
+ tx_status->retry_count = tx_resp->failure_frame;
+ tx_status->flags =
+ iwl_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
+ iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
+ &tx_status->control);
+
+ IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
+ "retries %d\n", txq_id, iwl_get_tx_fail_reason(status),
+ status, le32_to_cpu(tx_resp->rate_n_flags),
+ tx_resp->failure_frame);
+
+ IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
+#ifdef CONFIG_IWL4965_HT
+ if (index != -1) {
+ int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
+ if (tid != MAX_TID_COUNT)
+ priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+ if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
+ (txq_id >= 0) && priv->mac80211_registered)
+ ieee80211_wake_queue(priv->hw, txq_id);
+ if (tid != MAX_TID_COUNT)
+ iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
+ }
+ }
+#endif /* CONFIG_IWL4965_HT */
+
+ if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
+ IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
+}
+
+
+
/* Set up 4965-specific Rx frame reply handlers */
static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
{
@@ -3491,6 +3737,8 @@ static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl4965_rx_reply_rx;

+ priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
+
#ifdef CONFIG_IWL4965_HT
priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba;
#endif /* CONFIG_IWL4965_HT */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index e749b9f..0b753b5 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1595,250 +1595,6 @@ int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
* Generic RX handler implementations
*
******************************************************************************/
-#ifdef CONFIG_IWL4965_HT
-static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
-{
- __le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status +
- tx_resp->frame_count);
- return le32_to_cpu(*scd_ssn) & MAX_SN;
-
-}
-
-/**
- * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
- */
-static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
- struct iwl_ht_agg *agg,
- struct iwl4965_tx_resp_agg *tx_resp,
- u16 start_idx)
-{
- u16 status;
- struct agg_tx_status *frame_status = &tx_resp->status;
- struct ieee80211_tx_status *tx_status = NULL;
- struct ieee80211_hdr *hdr = NULL;
- int i, sh;
- int txq_id, idx;
- u16 seq;
-
- if (agg->wait_for_ba)
- IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n");
-
- agg->frame_count = tx_resp->frame_count;
- agg->start_idx = start_idx;
- agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
- agg->bitmap = 0;
-
- /* # frames attempted by Tx command */
- if (agg->frame_count == 1) {
- /* Only one frame was attempted; no block-ack will arrive */
- status = le16_to_cpu(frame_status[0].status);
- seq = le16_to_cpu(frame_status[0].sequence);
- idx = SEQ_TO_INDEX(seq);
- txq_id = SEQ_TO_QUEUE(seq);
-
- /* FIXME: code repetition */
- IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
- agg->frame_count, agg->start_idx, idx);
-
- tx_status = &(priv->txq[txq_id].txb[idx].status);
- tx_status->retry_count = tx_resp->failure_frame;
- tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU;
- tx_status->flags = iwl_is_tx_success(status)?
- IEEE80211_TX_STATUS_ACK : 0;
- iwl4965_hwrate_to_tx_control(priv,
- le32_to_cpu(tx_resp->rate_n_flags),
- &tx_status->control);
- /* FIXME: code repetition end */
-
- IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
- status & 0xff, tx_resp->failure_frame);
- IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n",
- iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags));
-
- agg->wait_for_ba = 0;
- } else {
- /* Two or more frames were attempted; expect block-ack */
- u64 bitmap = 0;
- int start = agg->start_idx;
-
- /* Construct bit-map of pending frames within Tx window */
- for (i = 0; i < agg->frame_count; i++) {
- u16 sc;
- status = le16_to_cpu(frame_status[i].status);
- seq = le16_to_cpu(frame_status[i].sequence);
- idx = SEQ_TO_INDEX(seq);
- txq_id = SEQ_TO_QUEUE(seq);
-
- if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
- AGG_TX_STATE_ABORT_MSK))
- continue;
-
- IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n",
- agg->frame_count, txq_id, idx);
-
- hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
-
- sc = le16_to_cpu(hdr->seq_ctrl);
- if (idx != (SEQ_TO_SN(sc) & 0xff)) {
- IWL_ERROR("BUG_ON idx doesn't match seq control"
- " idx=%d, seq_idx=%d, seq=%d\n",
- idx, SEQ_TO_SN(sc),
- hdr->seq_ctrl);
- return -1;
- }
-
- IWL_DEBUG_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n",
- i, idx, SEQ_TO_SN(sc));
-
- sh = idx - start;
- if (sh > 64) {
- sh = (start - idx) + 0xff;
- bitmap = bitmap << sh;
- sh = 0;
- start = idx;
- } else if (sh < -64)
- sh = 0xff - (start - idx);
- else if (sh < 0) {
- sh = start - idx;
- start = idx;
- bitmap = bitmap << sh;
- sh = 0;
- }
- bitmap |= (1 << sh);
- IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n",
- start, (u32)(bitmap & 0xFFFFFFFF));
- }
-
- agg->bitmap = bitmap;
- agg->start_idx = start;
- agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
- IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n",
- agg->frame_count, agg->start_idx,
- (unsigned long long)agg->bitmap);
-
- if (bitmap)
- agg->wait_for_ba = 1;
- }
- return 0;
-}
-#endif
-
-/**
- * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
- */
-static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- u16 sequence = le16_to_cpu(pkt->hdr.sequence);
- int txq_id = SEQ_TO_QUEUE(sequence);
- int index = SEQ_TO_INDEX(sequence);
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct ieee80211_tx_status *tx_status;
- struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
- u32 status = le32_to_cpu(tx_resp->status);
-#ifdef CONFIG_IWL4965_HT
- int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
- u16 fc;
- struct ieee80211_hdr *hdr;
- u8 *qc = NULL;
-#endif
-
- if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
- IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
- "is out of range [0-%d] %d %d\n", txq_id,
- index, txq->q.n_bd, txq->q.write_ptr,
- txq->q.read_ptr);
- return;
- }
-
-#ifdef CONFIG_IWL4965_HT
- hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
- fc = le16_to_cpu(hdr->frame_control);
- if (ieee80211_is_qos_data(fc)) {
- qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
- tid = qc[0] & 0xf;
- }
-
- sta_id = iwl_get_ra_sta_id(priv, hdr);
- if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
- IWL_ERROR("Station not known\n");
- return;
- }
-
- if (txq->sched_retry) {
- const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
- struct iwl_ht_agg *agg = NULL;
-
- if (!qc)
- return;
-
- agg = &priv->stations[sta_id].tid[tid].agg;
-
- iwl4965_tx_status_reply_tx(priv, agg,
- (struct iwl4965_tx_resp_agg *)tx_resp, index);
-
- if ((tx_resp->frame_count == 1) &&
- !iwl_is_tx_success(status)) {
- /* TODO: send BAR */
- }
-
- if (txq->q.read_ptr != (scd_ssn & 0xff)) {
- int freed, ampdu_q;
- index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
- IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
- "%d index %d\n", scd_ssn , index);
- freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
- priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
-
- if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
- txq_id >= 0 && priv->mac80211_registered &&
- agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
- /* calculate mac80211 ampdu sw queue to wake */
- ampdu_q = txq_id - IWL_BACK_QUEUE_FIRST_ID +
- priv->hw->queues;
- if (agg->state == IWL_AGG_OFF)
- ieee80211_wake_queue(priv->hw, txq_id);
- else
- ieee80211_wake_queue(priv->hw, ampdu_q);
- }
- iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
- }
- } else {
-#endif /* CONFIG_IWL4965_HT */
- tx_status = &(txq->txb[txq->q.read_ptr].status);
-
- tx_status->retry_count = tx_resp->failure_frame;
- tx_status->flags =
- iwl_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
- iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
- &tx_status->control);
-
- IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
- "retries %d\n", txq_id, iwl_get_tx_fail_reason(status),
- status, le32_to_cpu(tx_resp->rate_n_flags),
- tx_resp->failure_frame);
-
- IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
-#ifdef CONFIG_IWL4965_HT
- if (index != -1) {
- int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
- if (tid != MAX_TID_COUNT)
- priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
- if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
- (txq_id >= 0) && priv->mac80211_registered)
- ieee80211_wake_queue(priv->hw, txq_id);
- if (tid != MAX_TID_COUNT)
- iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
- }
- }
-#endif /* CONFIG_IWL4965_HT */
-
- if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
- IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
-}
-
-
static void iwl_rx_reply_alive(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
@@ -2207,7 +1963,6 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
iwl4965_rx_scan_complete_notif;
priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl4965_rx_card_state_notif;
- priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;

priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
iwl_rx_missed_beacon_notif;
--
1.5.3.6


2008-05-23 02:11:28

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: add ucode init flow handling for iwl5000

From: Ron Rindjunsky <[email protected]>

This patch adds all the handlers and functions needed for ucode
initialization flow.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-5000.c | 157 +++++++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-prph.h | 28 ++++++
2 files changed, 185 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index b6bdffc..5e818ee 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -46,6 +46,16 @@

#define IWL5000_UCODE_API "-1"

+static const u16 iwl5000_default_queue_to_tx_fifo[] = {
+ IWL_TX_FIFO_AC3,
+ IWL_TX_FIFO_AC2,
+ IWL_TX_FIFO_AC1,
+ IWL_TX_FIFO_AC0,
+ IWL50_CMD_FIFO_NUM,
+ IWL_TX_FIFO_HCCA_1,
+ IWL_TX_FIFO_HCCA_2
+};
+
static int iwl5000_apm_init(struct iwl_priv *priv)
{
int ret = 0;
@@ -420,6 +430,151 @@ static int iwl5000_load_ucode(struct iwl_priv *priv)
return ret;
}

+static void iwl5000_init_alive_start(struct iwl_priv *priv)
+{
+ int ret = 0;
+
+ /* Check alive response for "valid" sign from uCode */
+ if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
+ /* We had an error bringing up the hardware, so take it
+ * all the way back down so we can try again */
+ IWL_DEBUG_INFO("Initialize Alive failed.\n");
+ goto restart;
+ }
+
+ /* initialize uCode was loaded... verify inst image.
+ * This is a paranoid check, because we would not have gotten the
+ * "initialize" alive if code weren't properly loaded. */
+ if (iwl_verify_ucode(priv)) {
+ /* Runtime instruction load was bad;
+ * take it all the way back down so we can try again */
+ IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n");
+ goto restart;
+ }
+
+ iwlcore_clear_stations_table(priv);
+ ret = priv->cfg->ops->lib->alive_notify(priv);
+ if (ret) {
+ IWL_WARNING("Could not complete ALIVE transition: %d\n", ret);
+ goto restart;
+ }
+
+ return;
+
+restart:
+ /* real restart (first load init_ucode) */
+ queue_work(priv->workqueue, &priv->restart);
+}
+
+static void iwl5000_set_wr_ptrs(struct iwl_priv *priv,
+ int txq_id, u32 index)
+{
+ iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+ (index & 0xff) | (txq_id << 8));
+ iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index);
+}
+
+static void iwl5000_tx_queue_set_status(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq,
+ int tx_fifo_id, int scd_retry)
+{
+ int txq_id = txq->q.id;
+ int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0;
+
+ iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id),
+ (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
+ (tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) |
+ (1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) |
+ IWL50_SCD_QUEUE_STTS_REG_MSK);
+
+ txq->sched_retry = scd_retry;
+
+ IWL_DEBUG_INFO("%s %s Queue %d on AC %d\n",
+ active ? "Activate" : "Deactivate",
+ scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
+}
+
+static int iwl5000_alive_notify(struct iwl_priv *priv)
+{
+ u32 a;
+ int i = 0;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ ret = iwl_grab_nic_access(priv);
+ if (ret) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
+ }
+
+ priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR);
+ a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET;
+ for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET;
+ a += 4)
+ iwl_write_targ_mem(priv, a, 0);
+ for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET;
+ a += 4)
+ iwl_write_targ_mem(priv, a, 0);
+ for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4)
+ iwl_write_targ_mem(priv, a, 0);
+
+ iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR,
+ (priv->shared_phys +
+ offsetof(struct iwl5000_shared, queues_byte_cnt_tbls)) >> 10);
+ iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL,
+ IWL50_SCD_QUEUECHAIN_SEL_ALL(
+ priv->hw_params.max_txq_num));
+ iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0);
+
+ /* initiate the queues */
+ for (i = 0; i < priv->hw_params.max_txq_num; i++) {
+ iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0);
+ iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
+ iwl_write_targ_mem(priv, priv->scd_base_addr +
+ IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0);
+ iwl_write_targ_mem(priv, priv->scd_base_addr +
+ IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) +
+ sizeof(u32),
+ ((SCD_WIN_SIZE <<
+ IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
+ IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
+ ((SCD_FRAME_LIMIT <<
+ IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
+ IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
+ }
+
+ iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK,
+ (1 << priv->hw_params.max_txq_num) - 1);
+
+ iwl_write_prph(priv, IWL50_SCD_TXFACT,
+ SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
+
+ iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+ /* map qos queues to fifos one-to-one */
+ for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
+ int ac = iwl5000_default_queue_to_tx_fifo[i];
+ iwl_txq_ctx_activate(priv, i);
+ iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
+ }
+ /* TODO - need to initialize those FIFOs inside the loop above,
+ * not only mark them as active */
+ iwl_txq_ctx_activate(priv, 4);
+ iwl_txq_ctx_activate(priv, 7);
+ iwl_txq_ctx_activate(priv, 8);
+ iwl_txq_ctx_activate(priv, 9);
+
+ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* Ask for statistics now, the uCode will send notification
+ * periodically after association */
+ iwl_send_statistics_request(priv, CMD_ASYNC);
+
+ return 0;
+}
+
static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
{
if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) ||
@@ -622,6 +777,8 @@ static struct iwl_lib_ops iwl5000_lib = {
.disable_tx_fifo = iwl5000_disable_tx_fifo,
.rx_handler_setup = iwl5000_rx_handler_setup,
.load_ucode = iwl5000_load_ucode,
+ .init_alive_start = iwl5000_init_alive_start,
+ .alive_notify = iwl5000_alive_notify,
.apm_ops = {
.init = iwl5000_apm_init,
.config = iwl5000_nic_config,
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index acac629..d6a04f6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -517,6 +517,34 @@
#define IWL49_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF)

/* 5000 SCD */
+#define IWL50_SCD_QUEUE_STTS_REG_POS_TXF (0)
+#define IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE (3)
+#define IWL50_SCD_QUEUE_STTS_REG_POS_WSL (4)
+#define IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19)
+#define IWL50_SCD_QUEUE_STTS_REG_MSK (0x00FF0000)
+
+#define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_POS (8)
+#define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00)
+#define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24)
+#define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000)
+#define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0)
+#define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F)
+#define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16)
+#define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000)
+
+#define IWL50_SCD_CONTEXT_DATA_OFFSET (0x600)
+#define IWL50_SCD_TX_STTS_BITMAP_OFFSET (0x7B1)
+#define IWL50_SCD_TRANSLATE_TBL_OFFSET (0x7E0)
+
+#define IWL50_SCD_CONTEXT_QUEUE_OFFSET(x)\
+ (IWL50_SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
+
+#define IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
+ ((IWL50_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc)
+
+#define IWL50_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\
+ (~(1<<IWL_CMD_QUEUE_NUM)))
+
#define IWL50_SCD_BASE (PRPH_BASE + 0xa02c00)

#define IWL50_SCD_SRAM_BASE_ADDR (IWL50_SCD_BASE + 0x0)
--
1.5.3.6


2008-05-23 02:11:36

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: trigger event log from debugfs

From: Ester Kummer <[email protected]>

This patch adds a trigger for event log printing to debugfs.
It removes the triger from sysfs.

Signed-off-by: Ester Kummer <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-core.c | 101 ++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-core.h | 8 ++
drivers/net/wireless/iwlwifi/iwl-debug.h | 1 +
drivers/net/wireless/iwlwifi/iwl-debugfs.c | 32 ++++++++
drivers/net/wireless/iwlwifi/iwl4965-base.c | 114 +--------------------------
5 files changed, 143 insertions(+), 113 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 21f481e..7e25ca4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1055,3 +1055,104 @@ int iwl_verify_ucode(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_verify_ucode);

+
+#define EVENT_START_OFFSET (4 * sizeof(u32))
+
+/**
+ * iwl_print_event_log - Dump error event log to syslog
+ *
+ * NOTE: Must be called with iwl4965_grab_nic_access() already obtained!
+ */
+void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
+ u32 num_events, u32 mode)
+{
+ u32 i;
+ u32 base; /* SRAM byte address of event log header */
+ u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
+ u32 ptr; /* SRAM byte address of log data */
+ u32 ev, time, data; /* event log data */
+
+ if (num_events == 0)
+ return;
+
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
+ if (mode == 0)
+ event_size = 2 * sizeof(u32);
+ else
+ event_size = 3 * sizeof(u32);
+
+ ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+ /* "time" is actually "data" for mode 0 (no timestamp).
+ * place event id # at far right for easier visual parsing. */
+ for (i = 0; i < num_events; i++) {
+ ev = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ time = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ if (mode == 0)
+ IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
+ else {
+ data = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
+ }
+ }
+}
+EXPORT_SYMBOL(iwl_print_event_log);
+
+
+void iwl_dump_nic_event_log(struct iwl_priv *priv)
+{
+ int rc;
+ u32 base; /* SRAM byte address of event log header */
+ u32 capacity; /* event log capacity in # entries */
+ u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
+ u32 num_wraps; /* # times uCode wrapped to top of log */
+ u32 next_entry; /* index of next entry to be written by uCode */
+ u32 size; /* # entries that we'll print */
+
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
+ return;
+ }
+
+ rc = iwl_grab_nic_access(priv);
+ if (rc) {
+ IWL_WARNING("Can not read from adapter at this time.\n");
+ return;
+ }
+
+ /* event log header */
+ capacity = iwl_read_targ_mem(priv, base);
+ mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
+ num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
+ next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
+
+ size = num_wraps ? capacity : next_entry;
+
+ /* bail out if nothing in log */
+ if (size == 0) {
+ IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
+ iwl_release_nic_access(priv);
+ return;
+ }
+
+ IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n",
+ size, num_wraps);
+
+ /* if uCode has wrapped back to top of log, start at the oldest entry,
+ * i.e the next one that uCode would fill. */
+ if (num_wraps)
+ iwl_print_event_log(priv, next_entry,
+ capacity - next_entry, mode);
+ /* (then/else) start at top of log */
+ iwl_print_event_log(priv, 0, next_entry, mode);
+
+ iwl_release_nic_access(priv);
+}
+EXPORT_SYMBOL(iwl_dump_nic_event_log);
+
+
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 774aa7c..a8d062f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -232,6 +232,14 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
struct sk_buff *skb));

int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+
+/*****************************************************
+* Error Handling Debugging
+******************************************************/
+void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
+ u32 num_events, u32 mode);
+void iwl_dump_nic_event_log(struct iwl_priv *priv);
+
/*************** DRIVER STATUS FUNCTIONS *****/

#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index c3f8e90..11de561 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -52,6 +52,7 @@ struct iwl_debugfs {
struct dentry *file_stations;
struct dentry *file_rx_statistics;
struct dentry *file_tx_statistics;
+ struct dentry *file_log_event;
} dbgfs_data_files;
struct dir_rf_files {
#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index f7ec200..c64e602 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -92,6 +92,14 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
.open = iwl_dbgfs_open_file_generic, \
};

+#define DEBUGFS_WRITE_FILE_OPS(name) \
+ DEBUGFS_WRITE_FUNC(name); \
+static const struct file_operations iwl_dbgfs_##name##_ops = { \
+ .write = iwl_dbgfs_##name##_write, \
+ .open = iwl_dbgfs_open_file_generic, \
+};
+
+
#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
DEBUGFS_READ_FUNC(name); \
DEBUGFS_WRITE_FUNC(name); \
@@ -324,7 +332,29 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file,
return ret;
}

+static ssize_t iwl_dbgfs_log_event_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ u32 event_log_flag;
+ char buf[8];
+ int buf_size;
+
+ 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", &event_log_flag) != 1)
+ return -EFAULT;
+ if (event_log_flag == 1)
+ iwl_dump_nic_event_log(priv);
+
+ return count;
+}
+
DEBUGFS_READ_WRITE_FILE_OPS(sram);
+DEBUGFS_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(eeprom);
DEBUGFS_READ_FILE_OPS(stations);
DEBUGFS_READ_FILE_OPS(rx_statistics);
@@ -354,6 +384,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
DEBUGFS_ADD_FILE(eeprom, data);
DEBUGFS_ADD_FILE(sram, data);
+ DEBUGFS_ADD_FILE(log_event, data);
DEBUGFS_ADD_FILE(stations, data);
DEBUGFS_ADD_FILE(rx_statistics, data);
DEBUGFS_ADD_FILE(tx_statistics, data);
@@ -384,6 +415,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
DEBUGFS_REMOVE(priv->dbgfs->dir_data);
#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 05edde1..48c59cb 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -2692,103 +2692,6 @@ static void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
iwl_release_nic_access(priv);
}

-#define EVENT_START_OFFSET (4 * sizeof(u32))
-
-/**
- * iwl4965_print_event_log - Dump error event log to syslog
- *
- * NOTE: Must be called with iwl_grab_nic_access() already obtained!
- */
-static void iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode)
-{
- u32 i;
- u32 base; /* SRAM byte address of event log header */
- u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
-
- if (num_events == 0)
- return;
-
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
- if (mode == 0)
- event_size = 2 * sizeof(u32);
- else
- event_size = 3 * sizeof(u32);
-
- ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
- /* "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing. */
- for (i = 0; i < num_events; i++) {
- ev = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- time = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- if (mode == 0)
- IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
- else {
- data = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
- }
- }
-}
-
-static void iwl4965_dump_nic_event_log(struct iwl_priv *priv)
-{
- int rc;
- u32 base; /* SRAM byte address of event log header */
- u32 capacity; /* event log capacity in # entries */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
- u32 size; /* # entries that we'll print */
-
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
- return;
- }
-
- rc = iwl_grab_nic_access(priv);
- if (rc) {
- IWL_WARNING("Can not read from adapter at this time.\n");
- return;
- }
-
- /* event log header */
- capacity = iwl_read_targ_mem(priv, base);
- mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- size = num_wraps ? capacity : next_entry;
-
- /* bail out if nothing in log */
- if (size == 0) {
- IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
- iwl_release_nic_access(priv);
- return;
- }
-
- IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n",
- size, num_wraps);
-
- /* if uCode has wrapped back to top of log, start at the oldest entry,
- * i.e the next one that uCode would fill. */
- if (num_wraps)
- iwl4965_print_event_log(priv, next_entry,
- capacity - next_entry, mode);
-
- /* (then/else) start at top of log */
- iwl4965_print_event_log(priv, 0, next_entry, mode);
-
- iwl_release_nic_access(priv);
-}
-
/**
* iwl4965_irq_handle_error - called for HW or SW error interrupt from card
*/
@@ -2803,7 +2706,7 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
#ifdef CONFIG_IWLWIFI_DEBUG
if (priv->debug_level & IWL_DL_FW_ERRORS) {
iwl4965_dump_nic_error_log(priv);
- iwl4965_dump_nic_event_log(priv);
+ iwl_dump_nic_event_log(priv);
iwl4965_print_rx_config_cmd(priv);
}
#endif
@@ -5640,20 +5543,6 @@ static ssize_t dump_error_log(struct device *d,

static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);

-static ssize_t dump_event_log(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- char *p = (char *)buf;
-
- if (p[0] == '1')
- iwl4965_dump_nic_event_log((struct iwl_priv *)d->driver_data);
-
- return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
-
/*****************************************************************************
*
* driver setup and teardown
@@ -5700,7 +5589,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
static struct attribute *iwl4965_sysfs_entries[] = {
&dev_attr_channels.attr,
&dev_attr_dump_errors.attr,
- &dev_attr_dump_events.attr,
&dev_attr_flags.attr,
&dev_attr_filter_flags.attr,
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
--
1.5.3.6


2008-05-23 02:46:14

by Zhu Yi

[permalink] [raw]
Subject: Re: [PATCH 00/51] iwlwifi driver 05/23 updates

On Fri, 2008-05-23 at 10:08 +0800, Zhu Yi wrote:
> Here are some iwlwifi drivers update. Please apply.

I forgot to put a series number for each patch. If you think that
matters, I'll resubmit.

Thanks,
-yi


2008-05-23 02:11:53

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: implement apm reset flow

From: Tomas Winkler <[email protected]>

This patch implements apm reset flow for 4965 and 5000.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 36 +++++++++++-------
drivers/net/wireless/iwlwifi/iwl-5000.c | 54 +++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-core.h | 1 +
drivers/net/wireless/iwlwifi/iwl-dev.h | 1 -
drivers/net/wireless/iwlwifi/iwl4965-base.c | 5 +-
5 files changed, 79 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 02d3dc0..639ad50 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -646,9 +646,9 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
iwl_hw_txq_ctx_free(priv);
}

-int iwl4965_hw_nic_reset(struct iwl_priv *priv)
+static int iwl4965_apm_reset(struct iwl_priv *priv)
{
- int rc = 0;
+ int ret = 0;
unsigned long flags;

iwl4965_hw_nic_stop_master(priv);
@@ -659,33 +659,40 @@ int iwl4965_hw_nic_reset(struct iwl_priv *priv)

udelay(10);

+ /* FIXME: put here L1A -L0S w/a */
+
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- rc = iwl_poll_bit(priv, CSR_RESET,
+ ret = iwl_poll_bit(priv, CSR_RESET,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25);

+ if (ret)
+ goto out;
+
udelay(10);

- rc = iwl_grab_nic_access(priv);
- if (!rc) {
- iwl_write_prph(priv, APMG_CLK_EN_REG,
- APMG_CLK_VAL_DMA_CLK_RQT |
- APMG_CLK_VAL_BSM_CLK_RQT);
+ ret = iwl_grab_nic_access(priv);
+ if (ret)
+ goto out;
+ /* Enable DMA and BSM Clock */
+ iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT |
+ APMG_CLK_VAL_BSM_CLK_RQT);

- udelay(10);
+ udelay(10);

- iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
- APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+ /* disable L1A */
+ iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+ APMG_PCIDEV_STT_VAL_L1_ACT_DIS);

- iwl_release_nic_access(priv);
- }
+ iwl_release_nic_access(priv);

clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
wake_up_interruptible(&priv->wait_command_queue);

+out:
spin_unlock_irqrestore(&priv->lock, flags);

- return rc;
+ return ret;

}

@@ -3621,6 +3628,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.load_ucode = iwl4965_load_bsm,
.apm_ops = {
.init = iwl4965_apm_init,
+ .reset = iwl4965_apm_reset,
.config = iwl4965_nic_config,
.set_pwr_src = iwl4965_set_pwr_src,
},
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index b1c5045..10054bd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -100,6 +100,59 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
return ret;
}

+static int iwl5000_apm_reset(struct iwl_priv *priv)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ iwl4965_hw_nic_stop_master(priv);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+
+ udelay(10);
+
+
+ /* FIXME: put here L1A -L0S w/a */
+
+ iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
+
+ /* set "initialization complete" bit to move adapter
+ * D0U* --> D0A* state */
+ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+ /* wait for clock stabilization */
+ ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ if (ret < 0) {
+ IWL_DEBUG_INFO("Failed to init the card\n");
+ goto out;
+ }
+
+ ret = iwl_grab_nic_access(priv);
+ if (ret)
+ goto out;
+
+ /* enable DMA */
+ iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+
+ udelay(20);
+
+ /* disable L1-Active */
+ iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+ APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+
+ iwl_release_nic_access(priv);
+
+out:
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return ret;
+}
+
+
static void iwl5000_nic_config(struct iwl_priv *priv)
{
unsigned long flags;
@@ -805,6 +858,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.alive_notify = iwl5000_alive_notify,
.apm_ops = {
.init = iwl5000_apm_init,
+ .reset = iwl5000_apm_reset,
.config = iwl5000_nic_config,
.set_pwr_src = iwl4965_set_pwr_src,
},
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index e75bf34..70cc9d3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -124,6 +124,7 @@ struct iwl_lib_ops {
/* power management */
struct {
int (*init)(struct iwl_priv *priv);
+ int (*reset)(struct iwl_priv *priv);
void (*config)(struct iwl_priv *priv);
int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
} apm_ops;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 4c31164..38bd497 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -689,7 +689,6 @@ extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv);
extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv);
-extern int iwl4965_hw_nic_reset(struct iwl_priv *priv);
extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl_frame *frame, u8 rate);
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 857ec37..3cc55ff 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -3425,9 +3425,8 @@ static void __iwl4965_down(struct iwl_priv *priv)

udelay(5);

- iwl4965_hw_nic_stop_master(priv);
- iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- iwl4965_hw_nic_reset(priv);
+ /* FIXME: apm_ops.suspend(priv) */
+ priv->cfg->ops->lib->apm_ops.reset(priv);
priv->cfg->ops->lib->free_shared_mem(priv);

exit:
--
1.5.3.6


2008-05-23 02:11:11

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: get_hw_cmd_size

From: Gregory Greenman <[email protected]>

This patch introduces a new handler get_hw_cmd_size in hcmd_utils,
which should adjust the size of the command sent to the microcode
according to the current nic.
It also changes the RXON flow to make usage of this new handler.

The patch also adds iwl_rxon_cmd structure which is supperset for
5000 HW and 4965.

Signed-off-by: Gregory Greenman <[email protected]>
Signed-off-by: Zhu Yi <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 15 +++++++++++++--
drivers/net/wireless/iwlwifi/iwl-5000.c | 7 +++++++
drivers/net/wireless/iwlwifi/iwl-commands.h | 26 ++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-core.c | 2 +-
drivers/net/wireless/iwlwifi/iwl-core.h | 2 +-
drivers/net/wireless/iwlwifi/iwl-dev.h | 6 +++---
drivers/net/wireless/iwlwifi/iwl4965-base.c | 25 ++++++++++++++-----------
7 files changed, 65 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 2bb0075..83876a0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1857,8 +1857,8 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
{
int ret = 0;
struct iwl4965_rxon_assoc_cmd rxon_assoc;
- const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon;
- const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon;
+ const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
+ const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;

if ((rxon1->flags == rxon2->flags) &&
(rxon1->filter_flags == rxon2->filter_flags) &&
@@ -3743,6 +3743,16 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
#endif /* CONFIG_IWL4965_HT */


+static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len)
+{
+ switch (cmd_id) {
+ case REPLY_RXON:
+ return (u16) sizeof(struct iwl4965_rxon_cmd);
+ default:
+ return len;
+ }
+}
+
static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
{
struct iwl4965_addsta_cmd *addsta = (struct iwl4965_addsta_cmd *)data;
@@ -3802,6 +3812,7 @@ static struct iwl_hcmd_ops iwl4965_hcmd = {
};

static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
+ .get_hcmd_size = iwl4965_get_hcmd_size,
.enqueue_hcmd = iwl4965_enqueue_hcmd,
.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index b5e28b8..72d655c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -459,10 +459,17 @@ static int iwl5000_disable_tx_fifo(struct iwl_priv *priv)
return 0;
}

+/* Currently 5000 is the supperset of everything */
+static u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len)
+{
+ return len;
+}
+
static struct iwl_hcmd_ops iwl5000_hcmd = {
};

static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
+ .get_hcmd_size = iwl5000_get_hcmd_size,
.build_addsta_hcmd = iwl5000_build_addsta_hcmd,
#ifdef CONFIG_IWL5000_RUN_TIME_CALIB
.gain_computation = iwl5000_gain_computation,
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index d16a853..350af1b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -600,6 +600,32 @@ struct iwl4965_rxon_cmd {
u8 ofdm_ht_dual_stream_basic_rates;
} __attribute__ ((packed));

+/* 5000 HW just extend this cmmand */
+struct iwl_rxon_cmd {
+ u8 node_addr[6];
+ __le16 reserved1;
+ u8 bssid_addr[6];
+ __le16 reserved2;
+ u8 wlap_bssid_addr[6];
+ __le16 reserved3;
+ u8 dev_type;
+ u8 air_propagation;
+ __le16 rx_chain;
+ u8 ofdm_basic_rates;
+ u8 cck_basic_rates;
+ __le16 assoc_id;
+ __le32 flags;
+ __le32 filter_flags;
+ __le16 channel;
+ u8 ofdm_ht_single_stream_basic_rates;
+ u8 ofdm_ht_dual_stream_basic_rates;
+ u8 ofdm_ht_triple_stream_basic_rates;
+ u8 reserved5;
+ __le16 acquisition_data;
+ __le16 reserved6;
+} __attribute__ ((packed));
+
+
/*
* REPLY_RXON_ASSOC = 0x11 (command, has simple generic response)
*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index a2f4f28..b800031 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -588,7 +588,7 @@ EXPORT_SYMBOL(iwl_is_fat_tx_allowed);

void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
{
- struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
+ struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
u32 val;

if (!ht_info->is_ht)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index e139c8f..dcf1e56 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -86,6 +86,7 @@ struct iwl_hcmd_ops {
int (*rxon_assoc)(struct iwl_priv *priv);
};
struct iwl_hcmd_utils_ops {
+ u16 (*get_hcmd_size)(u8 cmd_id, u16 len);
int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data);
#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
@@ -303,5 +304,4 @@ static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
return priv->cfg->ops->hcmd->rxon_assoc(priv);
}

-
#endif /* __iwl_core_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index ae18a80..9a842fd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1009,11 +1009,11 @@ struct iwl_priv {
* changed via explicit cast within the
* routines that actually update the physical
* hardware */
- const struct iwl4965_rxon_cmd active_rxon;
- struct iwl4965_rxon_cmd staging_rxon;
+ const struct iwl_rxon_cmd active_rxon;
+ struct iwl_rxon_cmd staging_rxon;

int error_recovering;
- struct iwl4965_rxon_cmd recovery_rxon;
+ struct iwl_rxon_cmd recovery_rxon;

/* 1st responses from initialize and runtime uCode images.
* 4965's initialize alive response contains some calibration data. */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 6e70405..45b6b52 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -353,11 +353,14 @@ int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
u32 *control_flags;
struct iwl_cmd *out_cmd;
u32 idx;
- u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
+ u16 fix_size;
dma_addr_t phys_addr;
int ret;
unsigned long flags;

+ cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
+ fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
+
/* If any of the command structures end up being larger than
* the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
* we will need to increase the size of the TFD entries */
@@ -422,7 +425,7 @@ int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)

static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
{
- struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
+ struct iwl_rxon_cmd *rxon = &priv->staging_rxon;

if (hw_decrypt)
rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
@@ -470,7 +473,7 @@ static int iwl4965_rxon_add_station(struct iwl_priv *priv,
* be #ifdef'd out once the driver is stable and folks aren't actively
* making changes
*/
-static int iwl4965_check_rxon_cmd(struct iwl4965_rxon_cmd *rxon)
+static int iwl4965_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
{
int error = 0;
int counter = 1;
@@ -595,7 +598,7 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv)
static int iwl4965_commit_rxon(struct iwl_priv *priv)
{
/* cast away the const for active_rxon in this function */
- struct iwl4965_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
+ struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
DECLARE_MAC_BUF(mac);
int rc = 0;

@@ -640,7 +643,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;

rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
- sizeof(struct iwl4965_rxon_cmd),
+ sizeof(struct iwl_rxon_cmd),
&priv->active_rxon);

/* If the mask clearing failed then we set
@@ -665,7 +668,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
/* Apply the new configuration */
rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
- sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon);
+ sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
if (rc) {
IWL_ERROR("Error setting new configuration (%d).\n", rc);
return rc;
@@ -2699,7 +2702,7 @@ static void iwl4965_rx_reply_error(struct iwl_priv *priv,
static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- struct iwl4965_rxon_cmd *rxon = (void *)&priv->active_rxon;
+ struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
struct iwl4965_csa_notification *csa = &(pkt->u.csa_notif);
IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
le16_to_cpu(csa->channel), le32_to_cpu(csa->status));
@@ -3317,7 +3320,7 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
#ifdef CONFIG_IWLWIFI_DEBUG
static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv)
{
- struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
+ struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
DECLARE_MAC_BUF(mac);

IWL_DEBUG_RADIO("RX CONFIG:\n");
@@ -4213,8 +4216,8 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;

if (iwl_is_associated(priv)) {
- struct iwl4965_rxon_cmd *active_rxon =
- (struct iwl4965_rxon_cmd *)(&priv->active_rxon);
+ struct iwl_rxon_cmd *active_rxon =
+ (struct iwl_rxon_cmd *)&priv->active_rxon;

memcpy(&priv->staging_rxon, &priv->active_rxon,
sizeof(priv->staging_rxon));
@@ -5021,7 +5024,7 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw)
/* we should be verifying the device is ready to be opened */
mutex_lock(&priv->mutex);

- memset(&priv->staging_rxon, 0, sizeof(struct iwl4965_rxon_cmd));
+ memset(&priv->staging_rxon, 0, sizeof(struct iwl_rxon_cmd));
/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
* ucode filename and max sizes are card-specific. */

--
1.5.3.6


2008-05-23 02:11:34

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: refactor pci prob flow

From: Tomas Winkler <[email protected]>

This patch refactores pci prob flow. It moves mac80211 registration
to the end, otherwise there is a race between error path in pci_probe
and mac_start.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-core.c | 61 ++++++++++++++------------
drivers/net/wireless/iwlwifi/iwl-core.h | 6 +-
drivers/net/wireless/iwlwifi/iwl-eeprom.c | 1 -
drivers/net/wireless/iwlwifi/iwl4965-base.c | 31 ++++++++------
4 files changed, 54 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 79e46c5..21f481e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -518,12 +518,6 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
priv->bands[IEEE80211_BAND_2GHZ].n_channels,
priv->bands[IEEE80211_BAND_5GHZ].n_channels);

- if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
- priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
- &priv->bands[IEEE80211_BAND_2GHZ];
- if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
- priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
- &priv->bands[IEEE80211_BAND_5GHZ];

set_bit(STATUS_GEO_CONFIGURED, &priv->status);

@@ -533,13 +527,12 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
/*
* iwlcore_free_geos - undo allocations in iwlcore_init_geos
*/
-void iwlcore_free_geos(struct iwl_priv *priv)
+static void iwlcore_free_geos(struct iwl_priv *priv)
{
kfree(priv->ieee_channels);
kfree(priv->ieee_rates);
clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
}
-EXPORT_SYMBOL(iwlcore_free_geos);

#ifdef CONFIG_IWL4965_HT
static u8 is_single_rx_stream(struct iwl_priv *priv)
@@ -767,8 +760,9 @@ int iwl_set_rxon_channel(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_set_rxon_channel);

-static void iwlcore_init_hw(struct iwl_priv *priv)
+int iwl_setup_mac(struct iwl_priv *priv)
{
+ int ret;
struct ieee80211_hw *hw = priv->hw;
hw->rate_control_algorithm = "iwl-4965-rs";

@@ -782,9 +776,29 @@ static void iwlcore_init_hw(struct iwl_priv *priv)
/* Enhanced value; more queues, to support 11n aggregation */
hw->ampdu_queues = 12;
#endif /* CONFIG_IWL4965_HT */
+
+ hw->conf.beacon_int = 100;
+
+ if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
+ priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+ &priv->bands[IEEE80211_BAND_2GHZ];
+ if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
+ priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+ &priv->bands[IEEE80211_BAND_5GHZ];
+
+ ret = ieee80211_register_hw(priv->hw);
+ if (ret) {
+ IWL_ERROR("Failed to register hw (error %d)\n", ret);
+ return ret;
+ }
+ priv->mac80211_registered = 1;
+
+ return 0;
}
+EXPORT_SYMBOL(iwl_setup_mac);
+

-static int iwlcore_init_drv(struct iwl_priv *priv)
+int iwl_init_drv(struct iwl_priv *priv)
{
int ret;
int i;
@@ -821,6 +835,9 @@ static int iwlcore_init_drv(struct iwl_priv *priv)
/* Choose which receivers/antennas to use */
iwl_set_rxon_chain(priv);

+ if (priv->cfg->mod_params->enable_qos)
+ priv->qos_data.qos_enable = 1;
+
iwl_reset_qos(priv);

priv->qos_data.qos_active = 0;
@@ -845,34 +862,22 @@ static int iwlcore_init_drv(struct iwl_priv *priv)
goto err_free_channel_map;
}

- ret = ieee80211_register_hw(priv->hw);
- if (ret) {
- IWL_ERROR("Failed to register network device (error %d)\n",
- ret);
- goto err_free_geos;
- }
-
- priv->hw->conf.beacon_int = 100;
- priv->mac80211_registered = 1;
-
return 0;

-err_free_geos:
- iwlcore_free_geos(priv);
err_free_channel_map:
iwl_free_channel_map(priv);
err:
return ret;
}
+EXPORT_SYMBOL(iwl_init_drv);
+

-int iwl_setup(struct iwl_priv *priv)
+void iwl_uninit_drv(struct iwl_priv *priv)
{
- int ret = 0;
- iwlcore_init_hw(priv);
- ret = iwlcore_init_drv(priv);
- return ret;
+ iwlcore_free_geos(priv);
+ iwl_free_channel_map(priv);
}
-EXPORT_SYMBOL(iwl_setup);
+EXPORT_SYMBOL(iwl_uninit_drv);

/* Low level driver call this function to update iwlcore with
* driver status.
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index b159fd3..774aa7c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -175,13 +175,13 @@ void iwl_set_rxon_chain(struct iwl_priv *priv);
int iwl_set_rxon_channel(struct iwl_priv *priv,
enum ieee80211_band band,
u16 channel);
-void iwlcore_free_geos(struct iwl_priv *priv);
-int iwl_setup(struct iwl_priv *priv);
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
struct ieee80211_ht_info *sta_ht_inf);
int iwl_hw_nic_init(struct iwl_priv *priv);
-
+int iwl_setup_mac(struct iwl_priv *priv);
+int iwl_init_drv(struct iwl_priv *priv);
+void iwl_uninit_drv(struct iwl_priv *priv);
/* "keep warm" functions */
int iwl_kw_init(struct iwl_priv *priv);
int iwl_kw_alloc(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 300ef8e..e559c19 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -567,7 +567,6 @@ void iwl_free_channel_map(struct iwl_priv *priv)
kfree(priv->channel_info);
priv->channel_count = 0;
}
-EXPORT_SYMBOL(iwl_free_channel_map);

/**
* iwl_get_channel_info - Find driver's private channel info
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index e06142d..05edde1 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -5878,10 +5878,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
}

/*******************
- * 6. Setup hw/priv
+ * 6. Setup priv
*******************/

- err = iwl_setup(priv);
+ err = iwl_init_drv(priv);
if (err)
goto out_free_eeprom;
/* At this point both hw and priv are initialized. */
@@ -5896,9 +5896,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
IWL_DEBUG_INFO("Radio disabled.\n");
}

- if (priv->cfg->mod_params->enable_qos)
- priv->qos_data.qos_enable = 1;
-
/********************
* 8. Setup services
********************/
@@ -5909,14 +5906,9 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
if (err) {
IWL_ERROR("failed to create sysfs device attributes\n");
- goto out_free_eeprom;
+ goto out_uninit_drv;
}

- err = iwl_dbgfs_register(priv, DRV_NAME);
- if (err) {
- IWL_ERROR("failed to create debugfs files\n");
- goto out_remove_sysfs;
- }

iwl4965_setup_deferred_work(priv);
iwl4965_setup_rx_handlers(priv);
@@ -5927,12 +5919,26 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
pci_save_state(pdev);
pci_disable_device(pdev);

+ /**********************************
+ * 10. Setup and register mac80211
+ **********************************/
+
+ err = iwl_setup_mac(priv);
+ if (err)
+ goto out_remove_sysfs;
+
+ err = iwl_dbgfs_register(priv, DRV_NAME);
+ if (err)
+ IWL_ERROR("failed to create debugfs files\n");
+
/* notify iwlcore to init */
iwlcore_low_level_notify(priv, IWLCORE_INIT_EVT);
return 0;

out_remove_sysfs:
sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+ out_uninit_drv:
+ iwl_uninit_drv(priv);
out_free_eeprom:
iwl_eeprom_free(priv);
out_iounmap:
@@ -6014,8 +6020,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);

- iwl_free_channel_map(priv);
- iwlcore_free_geos(priv);
+ iwl_uninit_drv(priv);

if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);
--
1.5.3.6


2008-05-23 02:11:20

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: move TX code into iwl-tx.c

From: Tomas Winkler <[email protected]>

This patch moves the sending part of the TX code into iwl-tx.c
including sending host commands.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 105 -----
drivers/net/wireless/iwlwifi/iwl-core.h | 9 +-
drivers/net/wireless/iwlwifi/iwl-dev.h | 21 +-
drivers/net/wireless/iwlwifi/iwl-hcmd.c | 4 +-
drivers/net/wireless/iwlwifi/iwl-tx.c | 662 +++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl4965-base.c | 581 +-----------------------
6 files changed, 691 insertions(+), 691 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 02bbe04..8f0852d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1933,76 +1933,6 @@ int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
return rc;
}

-#define RTS_HCCA_RETRY_LIMIT 3
-#define RTS_DFAULT_RETRY_LIMIT 60
-
-void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
- struct ieee80211_tx_control *ctrl,
- struct ieee80211_hdr *hdr, int sta_id,
- int is_hcca)
-{
- struct iwl_tx_cmd *tx = &cmd->cmd.tx;
- u8 rts_retry_limit = 0;
- u8 data_retry_limit = 0;
- u16 fc = le16_to_cpu(hdr->frame_control);
- u8 rate_plcp;
- u16 rate_flags = 0;
- int rate_idx = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
-
- rate_plcp = iwl_rates[rate_idx].plcp;
-
- rts_retry_limit = (is_hcca) ?
- RTS_HCCA_RETRY_LIMIT : RTS_DFAULT_RETRY_LIMIT;
-
- if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
- rate_flags |= RATE_MCS_CCK_MSK;
-
-
- if (ieee80211_is_probe_response(fc)) {
- data_retry_limit = 3;
- if (data_retry_limit < rts_retry_limit)
- rts_retry_limit = data_retry_limit;
- } else
- data_retry_limit = IWL_DEFAULT_TX_RETRY;
-
- if (priv->data_retry_limit != -1)
- data_retry_limit = priv->data_retry_limit;
-
-
- if (ieee80211_is_data(fc)) {
- tx->initial_rate_index = 0;
- tx->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
- } else {
- switch (fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_AUTH:
- case IEEE80211_STYPE_DEAUTH:
- case IEEE80211_STYPE_ASSOC_REQ:
- case IEEE80211_STYPE_REASSOC_REQ:
- if (tx->tx_flags & TX_CMD_FLG_RTS_MSK) {
- tx->tx_flags &= ~TX_CMD_FLG_RTS_MSK;
- tx->tx_flags |= TX_CMD_FLG_CTS_MSK;
- }
- break;
- default:
- break;
- }
-
- /* Alternate between antenna A and B for successive frames */
- if (priv->use_ant_b_for_management_frame) {
- priv->use_ant_b_for_management_frame = 0;
- rate_flags |= RATE_MCS_ANT_B_MSK;
- } else {
- priv->use_ant_b_for_management_frame = 1;
- rate_flags |= RATE_MCS_ANT_A_MSK;
- }
- }
-
- tx->rts_retry_limit = rts_retry_limit;
- tx->data_retry_limit = data_retry_limit;
- tx->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
-}
-
static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv)
{
struct iwl4965_shared *s = priv->shared_virt;
@@ -2046,40 +1976,6 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
return (sizeof(*tx_beacon_cmd) + frame_size);
}

-int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
- dma_addr_t addr, u16 len)
-{
- int index, is_odd;
- struct iwl_tfd_frame *tfd = ptr;
- u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs);
-
- /* Each TFD can point to a maximum 20 Tx buffers */
- if ((num_tbs >= MAX_NUM_OF_TBS) || (num_tbs < 0)) {
- IWL_ERROR("Error can not send more than %d chunks\n",
- MAX_NUM_OF_TBS);
- return -EINVAL;
- }
-
- index = num_tbs / 2;
- is_odd = num_tbs & 0x1;
-
- if (!is_odd) {
- tfd->pa[index].tb1_addr = cpu_to_le32(addr);
- IWL_SET_BITS(tfd->pa[index], tb1_addr_hi,
- iwl_get_dma_hi_address(addr));
- IWL_SET_BITS(tfd->pa[index], tb1_len, len);
- } else {
- IWL_SET_BITS(tfd->pa[index], tb2_addr_lo16,
- (u32) (addr & 0xffff));
- IWL_SET_BITS(tfd->pa[index], tb2_addr_hi20, addr >> 16);
- IWL_SET_BITS(tfd->pa[index], tb2_len, len);
- }
-
- IWL_SET_BITS(*tfd, num_tbs, num_tbs + 1);
-
- return 0;
-}
-
static int iwl4965_alloc_shared_mem(struct iwl_priv *priv)
{
priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
@@ -3711,7 +3607,6 @@ static struct iwl_hcmd_ops iwl4965_hcmd = {

static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
.get_hcmd_size = iwl4965_get_hcmd_size,
- .enqueue_hcmd = iwl4965_enqueue_hcmd,
.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
.chain_noise_reset = iwl4965_chain_noise_reset,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index dcf1e56..b159fd3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -87,7 +87,6 @@ struct iwl_hcmd_ops {
};
struct iwl_hcmd_utils_ops {
u16 (*get_hcmd_size)(u8 cmd_id, u16 len);
- int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data);
#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
void (*gain_computation)(struct iwl_priv *priv,
@@ -208,10 +207,14 @@ void iwl_rx_allocate(struct iwl_priv *priv);
* TX
******************************************************/
int iwl_txq_ctx_reset(struct iwl_priv *priv);
+int iwl_tx_skb(struct iwl_priv *priv,
+ struct sk_buff *skb, struct ieee80211_tx_control *ctl);
/* FIXME: remove when free Tx is fully merged into iwlcore */
int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
-
+int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
+ dma_addr_t addr, u16 len);
+int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
/*****************************************************
* S e n d i n g H o s t C o m m a n d s *
*****************************************************/
@@ -227,6 +230,8 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
int (*callback)(struct iwl_priv *priv,
struct iwl_cmd *cmd,
struct sk_buff *skb));
+
+int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
/*************** DRIVER STATUS FUNCTIONS *****/

#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 7bd99f9..4106efd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -689,8 +689,6 @@ extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv);
extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv);
extern int iwl4965_hw_nic_reset(struct iwl_priv *priv);
-extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
- dma_addr_t addr, u16 len);
extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl_frame *frame, u8 rate);
@@ -719,6 +717,25 @@ extern u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid);
extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel);
extern int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
extern int iwl_queue_space(const struct iwl_queue *q);
+static inline int iwl_queue_used(const struct iwl_queue *q, int i)
+{
+ return q->write_ptr > q->read_ptr ?
+ (i >= q->read_ptr && i < q->write_ptr) :
+ !(i < q->read_ptr && i >= q->write_ptr);
+}
+
+
+static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
+{
+ /* This is for scan command, the big buffer at end of command array */
+ if (is_huge)
+ return q->n_window; /* must be power of 2 */
+
+ /* Otherwise, use normal size buffers */
+ return index & (q->n_window - 1);
+}
+
+
struct iwl_priv;

extern void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio);
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 0412adf..dab4a0e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -139,7 +139,7 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EBUSY;

- ret = priv->cfg->ops->utils->enqueue_hcmd(priv, cmd);
+ ret = iwl_enqueue_hcmd(priv, cmd);
if (ret < 0) {
IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret);
@@ -170,7 +170,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (cmd->meta.flags & CMD_WANT_SKB)
cmd->meta.source = &cmd->meta;

- cmd_idx = priv->cfg->ops->utils->enqueue_hcmd(priv, cmd);
+ cmd_idx = iwl_enqueue_hcmd(priv, cmd);
if (cmd_idx < 0) {
ret = cmd_idx;
IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 870d257..a37ced5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -27,6 +27,7 @@
*
*****************************************************************************/

+#include <linux/etherdevice.h>
#include <net/mac80211.h>
#include "iwl-eeprom.h"
#include "iwl-dev.h"
@@ -95,6 +96,89 @@ int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
}
EXPORT_SYMBOL(iwl_hw_txq_free_tfd);

+
+int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
+ dma_addr_t addr, u16 len)
+{
+ int index, is_odd;
+ struct iwl_tfd_frame *tfd = ptr;
+ u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs);
+
+ /* Each TFD can point to a maximum 20 Tx buffers */
+ if ((num_tbs >= MAX_NUM_OF_TBS) || (num_tbs < 0)) {
+ IWL_ERROR("Error can not send more than %d chunks\n",
+ MAX_NUM_OF_TBS);
+ return -EINVAL;
+ }
+
+ index = num_tbs / 2;
+ is_odd = num_tbs & 0x1;
+
+ if (!is_odd) {
+ tfd->pa[index].tb1_addr = cpu_to_le32(addr);
+ IWL_SET_BITS(tfd->pa[index], tb1_addr_hi,
+ iwl_get_dma_hi_address(addr));
+ IWL_SET_BITS(tfd->pa[index], tb1_len, len);
+ } else {
+ IWL_SET_BITS(tfd->pa[index], tb2_addr_lo16,
+ (u32) (addr & 0xffff));
+ IWL_SET_BITS(tfd->pa[index], tb2_addr_hi20, addr >> 16);
+ IWL_SET_BITS(tfd->pa[index], tb2_len, len);
+ }
+
+ IWL_SET_BITS(*tfd, num_tbs, num_tbs + 1);
+
+ return 0;
+}
+EXPORT_SYMBOL(iwl_hw_txq_attach_buf_to_tfd);
+
+/**
+ * iwl_txq_update_write_ptr - Send new write index to hardware
+ */
+int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+ u32 reg = 0;
+ int ret = 0;
+ int txq_id = txq->q.id;
+
+ if (txq->need_update == 0)
+ return ret;
+
+ /* if we're trying to save power */
+ if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+ /* wake up nic if it's powered down ...
+ * uCode will wake up, and interrupt us again, so next
+ * time we'll skip this part. */
+ reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+ if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+ IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
+ iwl_set_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ return ret;
+ }
+
+ /* restore this queue's parameters in nic hardware. */
+ ret = iwl_grab_nic_access(priv);
+ if (ret)
+ return ret;
+ iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+ txq->q.write_ptr | (txq_id << 8));
+ iwl_release_nic_access(priv);
+
+ /* else not in power-save mode, uCode will never sleep when we're
+ * trying to tx (during RFKILL, we're not trying to tx). */
+ } else
+ iwl_write32(priv, HBUS_TARG_WRPTR,
+ txq->q.write_ptr | (txq_id << 8));
+
+ txq->need_update = 0;
+
+ return ret;
+}
+EXPORT_SYMBOL(iwl_txq_update_write_ptr);
+
+
/**
* iwl_tx_queue_free - Deallocate DMA queue.
* @txq: Transmit queue to deallocate.
@@ -137,6 +221,47 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
memset(txq, 0, sizeof(*txq));
}

+/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
+ * DMA services
+ *
+ * Theory of operation
+ *
+ * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
+ * of buffer descriptors, each of which points to one or more data buffers for
+ * the device to read from or fill. Driver and device exchange status of each
+ * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty
+ * entries in each circular buffer, to protect against confusing empty and full
+ * queue states.
+ *
+ * The device reads or writes the data in the queues via the device's several
+ * DMA/FIFO channels. Each queue is mapped to a single DMA channel.
+ *
+ * For Tx queue, there are low mark and high mark limits. If, after queuing
+ * the packet for Tx, free space become < low mark, Tx queue stopped. When
+ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
+ * Tx queue resumed.
+ *
+ * See more detailed info in iwl-4965-hw.h.
+ ***************************************************/
+
+int iwl_queue_space(const struct iwl_queue *q)
+{
+ int s = q->read_ptr - q->write_ptr;
+
+ if (q->read_ptr > q->write_ptr)
+ s -= q->n_bd;
+
+ if (s <= 0)
+ s += q->n_window;
+ /* keep some reserve to not confuse empty and full situations */
+ s -= 2;
+ if (s < 0)
+ s = 0;
+ return s;
+}
+EXPORT_SYMBOL(iwl_queue_space);
+
+
/**
* iwl_hw_txq_ctx_free - Free TXQ Context
*
@@ -371,3 +496,540 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
error_kw:
return ret;
}
+
+/*
+ * handle build REPLY_TX command notification.
+ */
+static void iwl_tx_cmd_build_basic(struct iwl_priv *priv,
+ struct iwl_tx_cmd *tx_cmd,
+ struct ieee80211_tx_control *ctrl,
+ struct ieee80211_hdr *hdr,
+ int is_unicast, u8 std_id)
+{
+ u16 fc = le16_to_cpu(hdr->frame_control);
+ __le32 tx_flags = tx_cmd->tx_flags;
+
+ tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+ if (!(ctrl->flags & IEEE80211_TXCTL_NO_ACK)) {
+ tx_flags |= TX_CMD_FLG_ACK_MSK;
+ if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
+ tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+ if (ieee80211_is_probe_response(fc) &&
+ !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
+ tx_flags |= TX_CMD_FLG_TSF_MSK;
+ } else {
+ tx_flags &= (~TX_CMD_FLG_ACK_MSK);
+ tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+ }
+
+ if (ieee80211_is_back_request(fc))
+ tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
+
+
+ tx_cmd->sta_id = std_id;
+ if (ieee80211_get_morefrag(hdr))
+ tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
+
+ if (ieee80211_is_qos_data(fc)) {
+ u8 *qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
+ tx_cmd->tid_tspec = qc[0] & 0xf;
+ tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
+ } else {
+ tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+ }
+
+ if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
+ tx_flags |= TX_CMD_FLG_RTS_MSK;
+ tx_flags &= ~TX_CMD_FLG_CTS_MSK;
+ } else if (ctrl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
+ tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+ tx_flags |= TX_CMD_FLG_CTS_MSK;
+ }
+
+ if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
+ tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+
+ tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
+ if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
+ if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ ||
+ (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
+ tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
+ else
+ tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
+ } else {
+ tx_cmd->timeout.pm_frame_timeout = 0;
+ }
+
+ tx_cmd->driver_txop = 0;
+ tx_cmd->tx_flags = tx_flags;
+ tx_cmd->next_frame_len = 0;
+}
+
+#define RTS_HCCA_RETRY_LIMIT 3
+#define RTS_DFAULT_RETRY_LIMIT 60
+
+static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
+ struct iwl_tx_cmd *tx_cmd,
+ struct ieee80211_tx_control *ctrl,
+ u16 fc, int sta_id,
+ int is_hcca)
+{
+ u8 rts_retry_limit = 0;
+ u8 data_retry_limit = 0;
+ u8 rate_plcp;
+ u16 rate_flags = 0;
+ int rate_idx = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
+
+ rate_plcp = iwl_rates[rate_idx].plcp;
+
+ rts_retry_limit = (is_hcca) ?
+ RTS_HCCA_RETRY_LIMIT : RTS_DFAULT_RETRY_LIMIT;
+
+ if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
+ rate_flags |= RATE_MCS_CCK_MSK;
+
+
+ if (ieee80211_is_probe_response(fc)) {
+ data_retry_limit = 3;
+ if (data_retry_limit < rts_retry_limit)
+ rts_retry_limit = data_retry_limit;
+ } else
+ data_retry_limit = IWL_DEFAULT_TX_RETRY;
+
+ if (priv->data_retry_limit != -1)
+ data_retry_limit = priv->data_retry_limit;
+
+
+ if (ieee80211_is_data(fc)) {
+ tx_cmd->initial_rate_index = 0;
+ tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
+ } else {
+ switch (fc & IEEE80211_FCTL_STYPE) {
+ case IEEE80211_STYPE_AUTH:
+ case IEEE80211_STYPE_DEAUTH:
+ case IEEE80211_STYPE_ASSOC_REQ:
+ case IEEE80211_STYPE_REASSOC_REQ:
+ if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) {
+ tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+ tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Alternate between antenna A and B for successive frames */
+ if (priv->use_ant_b_for_management_frame) {
+ priv->use_ant_b_for_management_frame = 0;
+ rate_flags |= RATE_MCS_ANT_B_MSK;
+ } else {
+ priv->use_ant_b_for_management_frame = 1;
+ rate_flags |= RATE_MCS_ANT_A_MSK;
+ }
+ }
+
+ tx_cmd->rts_retry_limit = rts_retry_limit;
+ tx_cmd->data_retry_limit = data_retry_limit;
+ tx_cmd->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
+}
+
+static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
+ struct ieee80211_tx_control *ctl,
+ struct iwl_tx_cmd *tx_cmd,
+ struct sk_buff *skb_frag,
+ int sta_id)
+{
+ struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
+ struct iwl_wep_key *wepkey;
+ int keyidx = 0;
+
+ BUG_ON(ctl->hw_key->hw_key_idx > 3);
+
+ switch (keyinfo->alg) {
+ case ALG_CCMP:
+ tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
+ memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
+ if (ctl->flags & IEEE80211_TXCTL_AMPDU)
+ tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
+ IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
+ break;
+
+ case ALG_TKIP:
+ tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
+ ieee80211_get_tkip_key(keyinfo->conf, skb_frag,
+ IEEE80211_TKIP_P2_KEY, tx_cmd->key);
+ IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n");
+ break;
+
+ case ALG_WEP:
+ wepkey = &priv->wep_keys[ctl->hw_key->hw_key_idx];
+ tx_cmd->sec_ctl = 0;
+ if (priv->default_wep_key) {
+ /* the WEP key was sent as static */
+ keyidx = ctl->hw_key->hw_key_idx;
+ memcpy(&tx_cmd->key[3], wepkey->key,
+ wepkey->key_size);
+ if (wepkey->key_size == WEP_KEY_LEN_128)
+ tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+ } else {
+ /* the WEP key was sent as dynamic */
+ keyidx = keyinfo->keyidx;
+ memcpy(&tx_cmd->key[3], keyinfo->key,
+ keyinfo->keylen);
+ if (keyinfo->keylen == WEP_KEY_LEN_128)
+ tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+ }
+
+ tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP |
+ (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
+
+ IWL_DEBUG_TX("Configuring packet for WEP encryption "
+ "with key %d\n", keyidx);
+ break;
+
+ default:
+ printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
+ break;
+ }
+}
+
+static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len)
+{
+ /* 0 - mgmt, 1 - cnt, 2 - data */
+ int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
+ priv->tx_stats[idx].cnt++;
+ priv->tx_stats[idx].bytes += len;
+}
+
+/*
+ * start REPLY_TX command process
+ */
+int iwl_tx_skb(struct iwl_priv *priv,
+ struct sk_buff *skb, struct ieee80211_tx_control *ctl)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct iwl_tfd_frame *tfd;
+ u32 *control_flags;
+ int txq_id = ctl->queue;
+ struct iwl_tx_queue *txq = NULL;
+ struct iwl_queue *q = NULL;
+ dma_addr_t phys_addr;
+ dma_addr_t txcmd_phys;
+ dma_addr_t scratch_phys;
+ struct iwl_cmd *out_cmd = NULL;
+ struct iwl_tx_cmd *tx_cmd;
+ u16 len, idx, len_org;
+ u16 seq_number = 0;
+ u8 id, hdr_len, unicast;
+ u8 sta_id;
+ u16 fc;
+ u8 wait_write_ptr = 0;
+ u8 tid = 0;
+ u8 *qc = NULL;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (iwl_is_rfkill(priv)) {
+ IWL_DEBUG_DROP("Dropping - RF KILL\n");
+ goto drop_unlock;
+ }
+
+ if (!priv->vif) {
+ IWL_DEBUG_DROP("Dropping - !priv->vif\n");
+ goto drop_unlock;
+ }
+
+ if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
+ IWL_ERROR("ERROR: No TX rate available.\n");
+ goto drop_unlock;
+ }
+
+ unicast = !is_multicast_ether_addr(hdr->addr1);
+ id = 0;
+
+ fc = le16_to_cpu(hdr->frame_control);
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (ieee80211_is_auth(fc))
+ IWL_DEBUG_TX("Sending AUTH frame\n");
+ else if (ieee80211_is_assoc_request(fc))
+ IWL_DEBUG_TX("Sending ASSOC frame\n");
+ else if (ieee80211_is_reassoc_request(fc))
+ IWL_DEBUG_TX("Sending REASSOC frame\n");
+#endif
+
+ /* drop all data frame if we are not associated */
+ if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+ (!iwl_is_associated(priv) ||
+ ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) ||
+ !priv->assoc_station_added)) {
+ IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
+ goto drop_unlock;
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ hdr_len = ieee80211_get_hdrlen(fc);
+
+ /* Find (or create) index into station table for destination station */
+ sta_id = iwl_get_sta_id(priv, hdr);
+ if (sta_id == IWL_INVALID_STATION) {
+ DECLARE_MAC_BUF(mac);
+
+ IWL_DEBUG_DROP("Dropping - INVALID STATION: %s\n",
+ print_mac(mac, hdr->addr1));
+ goto drop;
+ }
+
+ IWL_DEBUG_TX("station Id %d\n", sta_id);
+
+ if (ieee80211_is_qos_data(fc)) {
+ qc = ieee80211_get_qos_ctrl(hdr, hdr_len);
+ tid = qc[0] & 0xf;
+ seq_number = priv->stations[sta_id].tid[tid].seq_number &
+ IEEE80211_SCTL_SEQ;
+ hdr->seq_ctrl = cpu_to_le16(seq_number) |
+ (hdr->seq_ctrl &
+ __constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
+ seq_number += 0x10;
+#ifdef CONFIG_IWL4965_HT
+ /* aggregation is on for this <sta,tid> */
+ if (ctl->flags & IEEE80211_TXCTL_AMPDU)
+ txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
+ priv->stations[sta_id].tid[tid].tfds_in_queue++;
+#endif /* CONFIG_IWL4965_HT */
+ }
+
+ /* Descriptor for chosen Tx queue */
+ txq = &priv->txq[txq_id];
+ q = &txq->q;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* Set up first empty TFD within this queue's circular TFD buffer */
+ tfd = &txq->bd[q->write_ptr];
+ memset(tfd, 0, sizeof(*tfd));
+ control_flags = (u32 *) tfd;
+ idx = get_cmd_index(q, q->write_ptr, 0);
+
+ /* Set up driver data for this TFD */
+ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
+ txq->txb[q->write_ptr].skb[0] = skb;
+ memcpy(&(txq->txb[q->write_ptr].status.control),
+ ctl, sizeof(struct ieee80211_tx_control));
+
+ /* Set up first empty entry in queue's array of Tx/cmd buffers */
+ out_cmd = &txq->cmd[idx];
+ tx_cmd = &out_cmd->cmd.tx;
+ memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
+ memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
+
+ /*
+ * Set up the Tx-command (not MAC!) header.
+ * Store the chosen Tx queue and TFD index within the sequence field;
+ * after Tx, uCode's Tx response will return this value so driver can
+ * locate the frame within the tx queue and do post-tx processing.
+ */
+ out_cmd->hdr.cmd = REPLY_TX;
+ out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
+ INDEX_TO_SEQ(q->write_ptr)));
+
+ /* Copy MAC header from skb into command buffer */
+ memcpy(tx_cmd->hdr, hdr, hdr_len);
+
+ /*
+ * Use the first empty entry in this queue's command buffer array
+ * to contain the Tx command and MAC header concatenated together
+ * (payload data will be in another buffer).
+ * Size of this varies, due to varying MAC header length.
+ * If end is not dword aligned, we'll have 2 extra bytes at the end
+ * of the MAC header (device reads on dword boundaries).
+ * We'll tell device about this padding later.
+ */
+ len = sizeof(struct iwl_tx_cmd) +
+ sizeof(struct iwl_cmd_header) + hdr_len;
+
+ len_org = len;
+ len = (len + 3) & ~3;
+
+ if (len_org != len)
+ len_org = 1;
+ else
+ len_org = 0;
+
+ /* Physical address of this Tx command's header (not MAC header!),
+ * within command buffer array. */
+ txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
+ offsetof(struct iwl_cmd, hdr);
+
+ /* Add buffer containing Tx command and MAC(!) header to TFD's
+ * first entry */
+ iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
+
+ if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
+ iwl_tx_cmd_build_hwcrypto(priv, ctl, tx_cmd, skb, sta_id);
+
+ /* Set up TFD's 2nd entry to point directly to remainder of skb,
+ * if any (802.11 null frames have no payload). */
+ len = skb->len - hdr_len;
+ if (len) {
+ phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
+ len, PCI_DMA_TODEVICE);
+ iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
+ }
+
+ /* Tell NIC about any 2-byte padding after MAC header */
+ if (len_org)
+ tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
+
+ /* Total # bytes to be transmitted */
+ len = (u16)skb->len;
+ tx_cmd->len = cpu_to_le16(len);
+ /* TODO need this for burst mode later on */
+ iwl_tx_cmd_build_basic(priv, tx_cmd, ctl, hdr, unicast, sta_id);
+
+ /* set is_hcca to 0; it probably will never be implemented */
+ iwl_tx_cmd_build_rate(priv, tx_cmd, ctl, fc, sta_id, 0);
+
+ iwl_update_tx_stats(priv, fc, len);
+
+ scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
+ offsetof(struct iwl_tx_cmd, scratch);
+ tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
+ tx_cmd->dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys);
+
+ if (!ieee80211_get_morefrag(hdr)) {
+ txq->need_update = 1;
+ if (qc)
+ priv->stations[sta_id].tid[tid].seq_number = seq_number;
+ } else {
+ wait_write_ptr = 1;
+ txq->need_update = 0;
+ }
+
+ iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
+
+ iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
+
+ /* Set up entry for this TFD in Tx byte-count array */
+ priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len);
+
+ /* Tell device the write index *just past* this latest filled TFD */
+ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+ ret = iwl_txq_update_write_ptr(priv, txq);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (ret)
+ return ret;
+
+ if ((iwl_queue_space(q) < q->high_mark)
+ && priv->mac80211_registered) {
+ if (wait_write_ptr) {
+ spin_lock_irqsave(&priv->lock, flags);
+ txq->need_update = 1;
+ iwl_txq_update_write_ptr(priv, txq);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+ ieee80211_stop_queue(priv->hw, ctl->queue);
+ }
+
+ return 0;
+
+drop_unlock:
+ spin_unlock_irqrestore(&priv->lock, flags);
+drop:
+ return -1;
+}
+EXPORT_SYMBOL(iwl_tx_skb);
+
+/*************** HOST COMMAND QUEUE FUNCTIONS *****/
+
+/**
+ * iwl_enqueue_hcmd - enqueue a uCode command
+ * @priv: device private data point
+ * @cmd: a point to the ucode command structure
+ *
+ * The function returns < 0 values to indicate the operation is
+ * failed. On success, it turns the index (> 0) of command in the
+ * command queue.
+ */
+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_tfd_frame *tfd;
+ u32 *control_flags;
+ struct iwl_cmd *out_cmd;
+ u32 idx;
+ u16 fix_size;
+ dma_addr_t phys_addr;
+ int ret;
+ unsigned long flags;
+
+ cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
+ fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
+
+ /* If any of the command structures end up being larger than
+ * 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));
+
+ if (iwl_is_rfkill(priv)) {
+ IWL_DEBUG_INFO("Not sending command - RF KILL");
+ return -EIO;
+ }
+
+ if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
+ IWL_ERROR("No space for Tx\n");
+ return -ENOSPC;
+ }
+
+ spin_lock_irqsave(&priv->hcmd_lock, flags);
+
+ tfd = &txq->bd[q->write_ptr];
+ memset(tfd, 0, sizeof(*tfd));
+
+ control_flags = (u32 *) tfd;
+
+ idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
+ out_cmd = &txq->cmd[idx];
+
+ 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
+ * information */
+
+ 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)
+ out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
+
+ phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
+ offsetof(struct iwl_cmd, hdr);
+ iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
+
+ IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
+ "%d bytes at %d[%d]:%d\n",
+ get_cmd_string(out_cmd->hdr.cmd),
+ out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
+ fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
+
+ txq->need_update = 1;
+
+ /* Set up entry in queue's byte count circular buffer */
+ priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
+
+ /* Increment and update queue's write index */
+ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+ ret = iwl_txq_update_write_ptr(priv, txq);
+
+ spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+ return ret ? ret : idx;
+}
+
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index e3f872e..dd2fd40 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -53,8 +53,6 @@
#include "iwl-sta.h"
#include "iwl-calib.h"

-static int iwl_txq_update_write_ptr(struct iwl_priv *priv,
- struct iwl_tx_queue *txq);

/******************************************************************************
*
@@ -135,69 +133,6 @@ static const char *iwl4965_escape_essid(const char *essid, u8 essid_len)
return escaped;
}

-
-/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
- * DMA services
- *
- * Theory of operation
- *
- * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
- * of buffer descriptors, each of which points to one or more data buffers for
- * the device to read from or fill. Driver and device exchange status of each
- * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty
- * entries in each circular buffer, to protect against confusing empty and full
- * queue states.
- *
- * The device reads or writes the data in the queues via the device's several
- * DMA/FIFO channels. Each queue is mapped to a single DMA channel.
- *
- * For Tx queue, there are low mark and high mark limits. If, after queuing
- * the packet for Tx, free space become < low mark, Tx queue stopped. When
- * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
- * Tx queue resumed.
- *
- * The 4965 operates with up to 17 queues: One receive queue, one transmit
- * queue (#4) for sending commands to the device firmware, and 15 other
- * Tx queues that may be mapped to prioritized Tx DMA/FIFO channels.
- *
- * See more detailed info in iwl-4965-hw.h.
- ***************************************************/
-
-int iwl_queue_space(const struct iwl_queue *q)
-{
- int s = q->read_ptr - q->write_ptr;
-
- if (q->read_ptr > q->write_ptr)
- s -= q->n_bd;
-
- if (s <= 0)
- s += q->n_window;
- /* keep some reserve to not confuse empty and full situations */
- s -= 2;
- if (s < 0)
- s = 0;
- return s;
-}
-
-
-static inline int iwl_queue_used(const struct iwl_queue *q, int i)
-{
- return q->write_ptr > q->read_ptr ?
- (i >= q->read_ptr && i < q->write_ptr) :
- !(i < q->read_ptr && i >= q->write_ptr);
-}
-
-static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
-{
- /* This is for scan command, the big buffer at end of command array */
- if (is_huge)
- return q->n_window; /* must be power of 2 */
-
- /* Otherwise, use normal size buffers */
- return index & (q->n_window - 1);
-}
-
-
/*************** STATION TABLE MANAGEMENT ****
* mac80211 should be examined to determine if sta_info is duplicating
* the functionality provided here
@@ -250,95 +185,6 @@ out:



-/*************** HOST COMMAND QUEUE FUNCTIONS *****/
-
-/**
- * iwl4965_enqueue_hcmd - enqueue a uCode command
- * @priv: device private data point
- * @cmd: a point to the ucode command structure
- *
- * The function returns < 0 values to indicate the operation is
- * failed. On success, it turns the index (> 0) of command in the
- * command queue.
- */
-int iwl4965_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_tfd_frame *tfd;
- u32 *control_flags;
- struct iwl_cmd *out_cmd;
- u32 idx;
- u16 fix_size;
- dma_addr_t phys_addr;
- int ret;
- unsigned long flags;
-
- cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
- fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
-
- /* If any of the command structures end up being larger than
- * 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));
-
- if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_INFO("Not sending command - RF KILL");
- return -EIO;
- }
-
- if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
- IWL_ERROR("No space for Tx\n");
- return -ENOSPC;
- }
-
- spin_lock_irqsave(&priv->hcmd_lock, flags);
-
- tfd = &txq->bd[q->write_ptr];
- memset(tfd, 0, sizeof(*tfd));
-
- control_flags = (u32 *) tfd;
-
- idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
- out_cmd = &txq->cmd[idx];
-
- 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
- * information */
-
- 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)
- out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
-
- phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
- offsetof(struct iwl_cmd, hdr);
- iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
-
- IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
- "%d bytes at %d[%d]:%d\n",
- get_cmd_string(out_cmd->hdr.cmd),
- out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
- fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
-
- txq->need_update = 1;
-
- /* Set up entry in queue's byte count circular buffer */
- priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
-
- /* Increment and update queue's write index */
- q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- ret = iwl_txq_update_write_ptr(priv, txq);
-
- spin_unlock_irqrestore(&priv->hcmd_lock, flags);
- return ret ? ret : idx;
-}
-
static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
{
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
@@ -1453,385 +1299,6 @@ static int iwl4965_set_mode(struct iwl_priv *priv, int mode)
return 0;
}

-static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
- struct ieee80211_tx_control *ctl,
- struct iwl_cmd *cmd,
- struct sk_buff *skb_frag,
- int sta_id)
-{
- struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
- struct iwl_wep_key *wepkey;
- int keyidx = 0;
-
- BUG_ON(ctl->hw_key->hw_key_idx > 3);
-
- switch (keyinfo->alg) {
- case ALG_CCMP:
- cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
- memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
- if (ctl->flags & IEEE80211_TXCTL_AMPDU)
- cmd->cmd.tx.tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
- IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
- break;
-
- case ALG_TKIP:
- cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP;
- ieee80211_get_tkip_key(keyinfo->conf, skb_frag,
- IEEE80211_TKIP_P2_KEY, cmd->cmd.tx.key);
- IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n");
- break;
-
- case ALG_WEP:
- wepkey = &priv->wep_keys[ctl->hw_key->hw_key_idx];
- cmd->cmd.tx.sec_ctl = 0;
- if (priv->default_wep_key) {
- /* the WEP key was sent as static */
- keyidx = ctl->hw_key->hw_key_idx;
- memcpy(&cmd->cmd.tx.key[3], wepkey->key,
- wepkey->key_size);
- if (wepkey->key_size == WEP_KEY_LEN_128)
- cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
- } else {
- /* the WEP key was sent as dynamic */
- keyidx = keyinfo->keyidx;
- memcpy(&cmd->cmd.tx.key[3], keyinfo->key,
- keyinfo->keylen);
- if (keyinfo->keylen == WEP_KEY_LEN_128)
- cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
- }
-
- cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP |
- (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
-
- IWL_DEBUG_TX("Configuring packet for WEP encryption "
- "with key %d\n", keyidx);
- break;
-
- default:
- printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
- break;
- }
-}
-
-/*
- * handle build REPLY_TX command notification.
- */
-static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
- struct ieee80211_tx_control *ctrl,
- struct ieee80211_hdr *hdr,
- int is_unicast, u8 std_id)
-{
- u16 fc = le16_to_cpu(hdr->frame_control);
- __le32 tx_flags = cmd->cmd.tx.tx_flags;
-
- cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
- if (!(ctrl->flags & IEEE80211_TXCTL_NO_ACK)) {
- tx_flags |= TX_CMD_FLG_ACK_MSK;
- if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
- tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
- if (ieee80211_is_probe_response(fc) &&
- !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
- tx_flags |= TX_CMD_FLG_TSF_MSK;
- } else {
- tx_flags &= (~TX_CMD_FLG_ACK_MSK);
- tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
- }
-
- if (ieee80211_is_back_request(fc))
- tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
-
-
- cmd->cmd.tx.sta_id = std_id;
- if (ieee80211_get_morefrag(hdr))
- tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
-
- if (ieee80211_is_qos_data(fc)) {
- u8 *qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
- cmd->cmd.tx.tid_tspec = qc[0] & 0xf;
- tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
- } else {
- tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
- }
-
- if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
- tx_flags |= TX_CMD_FLG_RTS_MSK;
- tx_flags &= ~TX_CMD_FLG_CTS_MSK;
- } else if (ctrl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
- tx_flags &= ~TX_CMD_FLG_RTS_MSK;
- tx_flags |= TX_CMD_FLG_CTS_MSK;
- }
-
- if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
- tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-
- tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
- if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
- if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ ||
- (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
- cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
- else
- cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
- } else {
- cmd->cmd.tx.timeout.pm_frame_timeout = 0;
- }
-
- cmd->cmd.tx.driver_txop = 0;
- cmd->cmd.tx.tx_flags = tx_flags;
- cmd->cmd.tx.next_frame_len = 0;
-}
-static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len)
-{
- /* 0 - mgmt, 1 - cnt, 2 - data */
- int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
- priv->tx_stats[idx].cnt++;
- priv->tx_stats[idx].bytes += len;
-}
-/*
- * start REPLY_TX command process
- */
-static int iwl4965_tx_skb(struct iwl_priv *priv,
- struct sk_buff *skb, struct ieee80211_tx_control *ctl)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct iwl_tfd_frame *tfd;
- u32 *control_flags;
- int txq_id = ctl->queue;
- struct iwl_tx_queue *txq = NULL;
- struct iwl_queue *q = NULL;
- dma_addr_t phys_addr;
- dma_addr_t txcmd_phys;
- dma_addr_t scratch_phys;
- struct iwl_cmd *out_cmd = NULL;
- u16 len, idx, len_org;
- u8 hdr_len;
- u8 id;
- u8 unicast;
- u8 sta_id;
- u8 tid = 0;
- u8 wait_write_ptr = 0;
- u16 seq_number = 0;
- u16 fc;
- u8 *qc = NULL;
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(&priv->lock, flags);
- if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_DROP("Dropping - RF KILL\n");
- goto drop_unlock;
- }
-
- if (!priv->vif) {
- IWL_DEBUG_DROP("Dropping - !priv->vif\n");
- goto drop_unlock;
- }
-
- if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
- IWL_ERROR("ERROR: No TX rate available.\n");
- goto drop_unlock;
- }
-
- unicast = !is_multicast_ether_addr(hdr->addr1);
- id = 0;
-
- fc = le16_to_cpu(hdr->frame_control);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (ieee80211_is_auth(fc))
- IWL_DEBUG_TX("Sending AUTH frame\n");
- else if (ieee80211_is_assoc_request(fc))
- IWL_DEBUG_TX("Sending ASSOC frame\n");
- else if (ieee80211_is_reassoc_request(fc))
- IWL_DEBUG_TX("Sending REASSOC frame\n");
-#endif
-
- /* drop all data frame if we are not associated */
- if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
- (!iwl_is_associated(priv) ||
- ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) ||
- !priv->assoc_station_added)) {
- IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
- goto drop_unlock;
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- hdr_len = ieee80211_get_hdrlen(fc);
-
- /* Find (or create) index into station table for destination station */
- sta_id = iwl_get_sta_id(priv, hdr);
- if (sta_id == IWL_INVALID_STATION) {
- DECLARE_MAC_BUF(mac);
-
- IWL_DEBUG_DROP("Dropping - INVALID STATION: %s\n",
- print_mac(mac, hdr->addr1));
- goto drop;
- }
-
- IWL_DEBUG_TX("station Id %d\n", sta_id);
-
- if (ieee80211_is_qos_data(fc)) {
- qc = ieee80211_get_qos_ctrl(hdr, hdr_len);
- tid = qc[0] & 0xf;
- seq_number = priv->stations[sta_id].tid[tid].seq_number &
- IEEE80211_SCTL_SEQ;
- hdr->seq_ctrl = cpu_to_le16(seq_number) |
- (hdr->seq_ctrl &
- __constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
- seq_number += 0x10;
-#ifdef CONFIG_IWL4965_HT
- /* aggregation is on for this <sta,tid> */
- if (ctl->flags & IEEE80211_TXCTL_AMPDU)
- txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
- priv->stations[sta_id].tid[tid].tfds_in_queue++;
-#endif /* CONFIG_IWL4965_HT */
- }
-
- /* Descriptor for chosen Tx queue */
- txq = &priv->txq[txq_id];
- q = &txq->q;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* Set up first empty TFD within this queue's circular TFD buffer */
- tfd = &txq->bd[q->write_ptr];
- memset(tfd, 0, sizeof(*tfd));
- control_flags = (u32 *) tfd;
- idx = get_cmd_index(q, q->write_ptr, 0);
-
- /* Set up driver data for this TFD */
- memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
- txq->txb[q->write_ptr].skb[0] = skb;
- memcpy(&(txq->txb[q->write_ptr].status.control),
- ctl, sizeof(struct ieee80211_tx_control));
-
- /* Set up first empty entry in queue's array of Tx/cmd buffers */
- out_cmd = &txq->cmd[idx];
- memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
- memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx));
-
- /*
- * Set up the Tx-command (not MAC!) header.
- * Store the chosen Tx queue and TFD index within the sequence field;
- * after Tx, uCode's Tx response will return this value so driver can
- * locate the frame within the tx queue and do post-tx processing.
- */
- out_cmd->hdr.cmd = REPLY_TX;
- out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
- INDEX_TO_SEQ(q->write_ptr)));
-
- /* Copy MAC header from skb into command buffer */
- memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len);
-
- /*
- * Use the first empty entry in this queue's command buffer array
- * to contain the Tx command and MAC header concatenated together
- * (payload data will be in another buffer).
- * Size of this varies, due to varying MAC header length.
- * If end is not dword aligned, we'll have 2 extra bytes at the end
- * of the MAC header (device reads on dword boundaries).
- * We'll tell device about this padding later.
- */
- len = sizeof(struct iwl_tx_cmd) +
- sizeof(struct iwl_cmd_header) + hdr_len;
-
- len_org = len;
- len = (len + 3) & ~3;
-
- if (len_org != len)
- len_org = 1;
- else
- len_org = 0;
-
- /* Physical address of this Tx command's header (not MAC header!),
- * within command buffer array. */
- txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
- offsetof(struct iwl_cmd, hdr);
-
- /* Add buffer containing Tx command and MAC(!) header to TFD's
- * first entry */
- iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
-
- if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
- iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, sta_id);
-
- /* Set up TFD's 2nd entry to point directly to remainder of skb,
- * if any (802.11 null frames have no payload). */
- len = skb->len - hdr_len;
- if (len) {
- phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
- len, PCI_DMA_TODEVICE);
- iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
- }
-
- /* Tell 4965 about any 2-byte padding after MAC header */
- if (len_org)
- out_cmd->cmd.tx.tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
-
- /* Total # bytes to be transmitted */
- len = (u16)skb->len;
- out_cmd->cmd.tx.len = cpu_to_le16(len);
-
- /* TODO need this for burst mode later on */
- iwl4965_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id);
-
- /* set is_hcca to 0; it probably will never be implemented */
- iwl4965_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
-
- iwl_update_tx_stats(priv, fc, len);
-
- scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
- offsetof(struct iwl_tx_cmd, scratch);
- out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys);
- out_cmd->cmd.tx.dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys);
-
- if (!ieee80211_get_morefrag(hdr)) {
- txq->need_update = 1;
- if (qc)
- priv->stations[sta_id].tid[tid].seq_number = seq_number;
- } else {
- wait_write_ptr = 1;
- txq->need_update = 0;
- }
-
- iwl_print_hex_dump(priv, IWL_DL_TX, out_cmd->cmd.payload,
- sizeof(out_cmd->cmd.tx));
-
- iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
- ieee80211_get_hdrlen(fc));
-
- /* Set up entry for this TFD in Tx byte-count array */
- priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len);
-
- /* Tell device the write index *just past* this latest filled TFD */
- q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- rc = iwl_txq_update_write_ptr(priv, txq);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if (rc)
- return rc;
-
- if ((iwl_queue_space(q) < q->high_mark)
- && priv->mac80211_registered) {
- if (wait_write_ptr) {
- spin_lock_irqsave(&priv->lock, flags);
- txq->need_update = 1;
- iwl_txq_update_write_ptr(priv, txq);
- spin_unlock_irqrestore(&priv->lock, flags);
- }
-
- ieee80211_stop_queue(priv->hw, ctl->queue);
- }
-
- return 0;
-
-drop_unlock:
- spin_unlock_irqrestore(&priv->lock, flags);
-drop:
- return -1;
-}
-
static void iwl4965_set_rate(struct iwl_priv *priv)
{
const struct ieee80211_supported_band *hw = NULL;
@@ -3101,52 +2568,6 @@ int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
return sig_qual;
}

-/**
- * iwl_txq_update_write_ptr - Send new write index to hardware
- */
-static int iwl_txq_update_write_ptr(struct iwl_priv *priv,
- struct iwl_tx_queue *txq)
-{
- u32 reg = 0;
- int ret = 0;
- int txq_id = txq->q.id;
-
- if (txq->need_update == 0)
- return ret;
-
- /* if we're trying to save power */
- if (test_bit(STATUS_POWER_PMI, &priv->status)) {
- /* wake up nic if it's powered down ...
- * uCode will wake up, and interrupt us again, so next
- * time we'll skip this part. */
- reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
-
- if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
- IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
- iwl_set_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- return ret;
- }
-
- /* restore this queue's parameters in nic hardware. */
- ret = iwl_grab_nic_access(priv);
- if (ret)
- return ret;
- iwl_write_direct32(priv, HBUS_TARG_WRPTR,
- txq->q.write_ptr | (txq_id << 8));
- iwl_release_nic_access(priv);
-
- /* else not in power-save mode, uCode will never sleep when we're
- * trying to tx (during RFKILL, we're not trying to tx). */
- } else
- iwl_write32(priv, HBUS_TARG_WRPTR,
- txq->q.write_ptr | (txq_id << 8));
-
- txq->need_update = 0;
-
- return ret;
-}
-
#ifdef CONFIG_IWLWIFI_DEBUG
static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv)
{
@@ -4956,7 +4377,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
ctl->tx_rate->bitrate);

- if (iwl4965_tx_skb(priv, skb, ctl))
+ if (iwl_tx_skb(priv, skb, ctl))
dev_kfree_skb_any(skb);

IWL_DEBUG_MAC80211("leave\n");
--
1.5.3.6


2008-05-23 02:12:10

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: move tx response common handlers to iwlcore

From: Tomas Winkler <[email protected]>

This pach moves common tx response handlers to the header files
and iwl-tx.c.

Signed-off-by: Tomas Winkler <[email protected]>
Signed-off-by: Ron Rindjunsky <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-commands.h | 9 ++++
drivers/net/wireless/iwlwifi/iwl-core.h | 3 +
drivers/net/wireless/iwlwifi/iwl-dev.h | 30 ++++++++++++
drivers/net/wireless/iwlwifi/iwl-tx.c | 30 ++++++++++++
drivers/net/wireless/iwlwifi/iwl4965-base.c | 68 +++------------------------
5 files changed, 79 insertions(+), 61 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index bad0e94..2652e37 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -1365,6 +1365,15 @@ enum {
TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */
};

+static inline int iwl_is_tx_success(u32 status)
+{
+ status &= TX_STATUS_MSK;
+ return (status == TX_STATUS_SUCCESS)
+ || (status == TX_STATUS_DIRECT_DONE);
+}
+
+
+
/* *******************************
* TX aggregation status
******************************* */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 4fe7a9b..7ccaf80 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -209,6 +209,8 @@ void iwl_rx_allocate(struct iwl_priv *priv);
void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);

+/* TX helpers */
+
/*****************************************************
* TX
******************************************************/
@@ -221,6 +223,7 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
dma_addr_t addr, u16 len);
int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+
/*****************************************************
* S e n d i n g H o s t C o m m a n d s *
*****************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 924a1f4..16c0a91 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1243,6 +1243,36 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
clear_bit(txq_id, &priv->txq_ctx_active_msk);
}

+#ifdef CONFIG_IWLWIF_DEBUG
+const char *iwl_get_tx_fail_reason(u32 status);
+#else
+static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; }
+#endif
+
+
+#ifdef CONFIG_IWL4965_HT
+static inline int iwl_get_ra_sta_id(struct iwl_priv *priv,
+ struct ieee80211_hdr *hdr)
+{
+ if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
+ return IWL_AP_ID;
+ } else {
+ u8 *da = ieee80211_get_DA(hdr);
+ return iwl_find_station(priv, da);
+ }
+}
+
+static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv,
+ int txq_id, int idx)
+{
+ if (priv->txq[txq_id].txb[idx].skb[0])
+ return (struct ieee80211_hdr *)priv->txq[txq_id].
+ txb[idx].skb[0]->data;
+ return NULL;
+}
+#endif
+
+
static inline int iwl_is_associated(struct iwl_priv *priv)
{
return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index f73d690..70920bf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -1058,3 +1058,33 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
return ret ? ret : idx;
}

+#ifdef CONFIG_IWLWIF_DEBUG
+#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
+
+const char *iwl_get_tx_fail_reason(u32 status)
+{
+ switch (status & TX_STATUS_MSK) {
+ case TX_STATUS_SUCCESS:
+ return "SUCCESS";
+ TX_STATUS_ENTRY(SHORT_LIMIT);
+ TX_STATUS_ENTRY(LONG_LIMIT);
+ TX_STATUS_ENTRY(FIFO_UNDERRUN);
+ TX_STATUS_ENTRY(MGMNT_ABORT);
+ TX_STATUS_ENTRY(NEXT_FRAG);
+ TX_STATUS_ENTRY(LIFE_EXPIRE);
+ TX_STATUS_ENTRY(DEST_PS);
+ TX_STATUS_ENTRY(ABORTED);
+ TX_STATUS_ENTRY(BT_RETRY);
+ TX_STATUS_ENTRY(STA_INVALID);
+ TX_STATUS_ENTRY(FRAG_DROPPED);
+ TX_STATUS_ENTRY(TID_DISABLE);
+ TX_STATUS_ENTRY(FRAME_FLUSHED);
+ TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
+ TX_STATUS_ENTRY(TX_LOCKED);
+ TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
+ }
+
+ return "UNKNOWN";
+}
+EXPORT_SYMBOL(iwl_get_tx_fail_reason);
+#endif /* CONFIG_IWLWIFI_DEBUG */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index e46bdb1..e749b9f 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -915,33 +915,7 @@ int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *heade
return 1;
}

-#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x

-static const char *iwl4965_get_tx_fail_reason(u32 status)
-{
- switch (status & TX_STATUS_MSK) {
- case TX_STATUS_SUCCESS:
- return "SUCCESS";
- TX_STATUS_ENTRY(SHORT_LIMIT);
- TX_STATUS_ENTRY(LONG_LIMIT);
- TX_STATUS_ENTRY(FIFO_UNDERRUN);
- TX_STATUS_ENTRY(MGMNT_ABORT);
- TX_STATUS_ENTRY(NEXT_FRAG);
- TX_STATUS_ENTRY(LIFE_EXPIRE);
- TX_STATUS_ENTRY(DEST_PS);
- TX_STATUS_ENTRY(ABORTED);
- TX_STATUS_ENTRY(BT_RETRY);
- TX_STATUS_ENTRY(STA_INVALID);
- TX_STATUS_ENTRY(FRAG_DROPPED);
- TX_STATUS_ENTRY(TID_DISABLE);
- TX_STATUS_ENTRY(FRAME_FLUSHED);
- TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
- TX_STATUS_ENTRY(TX_LOCKED);
- TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
- }
-
- return "UNKNOWN";
-}

/**
* iwl4965_scan_cancel - Cancel any currently executing HW scan
@@ -1616,40 +1590,12 @@ int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
return nfreed;
}

-static int iwl4965_is_tx_success(u32 status)
-{
- status &= TX_STATUS_MSK;
- return (status == TX_STATUS_SUCCESS)
- || (status == TX_STATUS_DIRECT_DONE);
-}
-
/******************************************************************************
*
* Generic RX handler implementations
*
******************************************************************************/
#ifdef CONFIG_IWL4965_HT
-
-static inline int iwl4965_get_ra_sta_id(struct iwl_priv *priv,
- struct ieee80211_hdr *hdr)
-{
- if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
- return IWL_AP_ID;
- else {
- u8 *da = ieee80211_get_DA(hdr);
- return iwl_find_station(priv, da);
- }
-}
-
-static struct ieee80211_hdr *iwl4965_tx_queue_get_hdr(
- struct iwl_priv *priv, int txq_id, int idx)
-{
- if (priv->txq[txq_id].txb[idx].skb[0])
- return (struct ieee80211_hdr *)priv->txq[txq_id].
- txb[idx].skb[0]->data;
- return NULL;
-}
-
static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
{
__le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status +
@@ -1697,7 +1643,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
tx_status = &(priv->txq[txq_id].txb[idx].status);
tx_status->retry_count = tx_resp->failure_frame;
tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU;
- tx_status->flags = iwl4965_is_tx_success(status)?
+ tx_status->flags = iwl_is_tx_success(status)?
IEEE80211_TX_STATUS_ACK : 0;
iwl4965_hwrate_to_tx_control(priv,
le32_to_cpu(tx_resp->rate_n_flags),
@@ -1730,7 +1676,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n",
agg->frame_count, txq_id, idx);

- hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, idx);
+ hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);

sc = le16_to_cpu(hdr->seq_ctrl);
if (idx != (SEQ_TO_SN(sc) & 0xff)) {
@@ -1807,14 +1753,14 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
}

#ifdef CONFIG_IWL4965_HT
- hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, index);
+ hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
fc = le16_to_cpu(hdr->frame_control);
if (ieee80211_is_qos_data(fc)) {
qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
tid = qc[0] & 0xf;
}

- sta_id = iwl4965_get_ra_sta_id(priv, hdr);
+ sta_id = iwl_get_ra_sta_id(priv, hdr);
if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
IWL_ERROR("Station not known\n");
return;
@@ -1833,7 +1779,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
(struct iwl4965_tx_resp_agg *)tx_resp, index);

if ((tx_resp->frame_count == 1) &&
- !iwl4965_is_tx_success(status)) {
+ !iwl_is_tx_success(status)) {
/* TODO: send BAR */
}

@@ -1864,12 +1810,12 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,

tx_status->retry_count = tx_resp->failure_frame;
tx_status->flags =
- iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
+ iwl_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
&tx_status->control);

IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
- "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status),
+ "retries %d\n", txq_id, iwl_get_tx_fail_reason(status),
status, le32_to_cpu(tx_resp->rate_n_flags),
tx_resp->failure_frame);

--
1.5.3.6


2008-05-23 02:11:08

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: rename iwl4965_tx_info to iwl_tx_info

From: Tomas Winkler <[email protected]>

This patch renames iwl4965_tx_info to iwl_tx_info.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ++--
drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index cf99224..ae18a80 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -118,7 +118,7 @@ struct iwl_queue {
#define MAX_NUM_OF_TBS (20)

/* One for each TFD */
-struct iwl4965_tx_info {
+struct iwl_tx_info {
struct ieee80211_tx_status status;
struct sk_buff *skb[MAX_NUM_OF_TBS];
};
@@ -141,7 +141,7 @@ struct iwl_tx_queue {
struct iwl_tfd_frame *bd;
struct iwl_cmd *cmd;
dma_addr_t dma_addr_cmd;
- struct iwl4965_tx_info *txb;
+ struct iwl_tx_info *txb;
int need_update;
int sched_retry;
int active;
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 2e7e616..6e70405 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1868,7 +1868,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
idx = get_cmd_index(q, q->write_ptr, 0);

/* Set up driver data for this TFD */
- memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl4965_tx_info));
+ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
txq->txb[q->write_ptr].skb[0] = skb;
memcpy(&(txq->txb[q->write_ptr].status.control),
ctl, sizeof(struct ieee80211_tx_control));
@@ -2306,7 +2306,7 @@ static int iwl4965_get_measurement(struct iwl_priv *priv,
#endif

static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv,
- struct iwl4965_tx_info *tx_sta)
+ struct iwl_tx_info *tx_sta)
{

tx_sta->status.ack_signal = 0;
--
1.5.3.6


2008-05-23 02:11:37

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: move iwl_dump_nic_error_log to iwlcore module

From: Ester Kummer <[email protected]>

This patch moves the function iwl_dump_nic_error_log to iwlcore.
Remove sysfs entry it cannot be really triggered.

Signed-off-by: Ester Kummer <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-core.c | 72 ++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-core.h | 1 +
drivers/net/wireless/iwlwifi/iwl4965-base.c | 87 +--------------------------
3 files changed, 74 insertions(+), 86 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 7e25ca4..785396f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1056,6 +1056,78 @@ int iwl_verify_ucode(struct iwl_priv *priv)
EXPORT_SYMBOL(iwl_verify_ucode);


+static const char *desc_lookup(int i)
+{
+ switch (i) {
+ case 1:
+ return "FAIL";
+ case 2:
+ return "BAD_PARAM";
+ case 3:
+ return "BAD_CHECKSUM";
+ case 4:
+ return "NMI_INTERRUPT";
+ case 5:
+ return "SYSASSERT";
+ case 6:
+ return "FATAL_ERROR";
+ }
+
+ return "UNKNOWN";
+}
+
+#define ERROR_START_OFFSET (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE (7 * sizeof(u32))
+
+void iwl_dump_nic_error_log(struct iwl_priv *priv)
+{
+ u32 data2, line;
+ u32 desc, time, count, base, data1;
+ u32 blink1, blink2, ilink1, ilink2;
+ int rc;
+
+ base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
+ return;
+ }
+
+ rc = iwl_grab_nic_access(priv);
+ if (rc) {
+ IWL_WARNING("Can not read from adapter at this time.\n");
+ return;
+ }
+
+ count = iwl_read_targ_mem(priv, base);
+
+ if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ IWL_ERROR("Start IWL Error Log Dump:\n");
+ IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
+ }
+
+ desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
+ blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
+ blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
+ ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
+ ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
+ data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
+ data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
+ line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
+ time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
+
+ IWL_ERROR("Desc Time "
+ "data1 data2 line\n");
+ IWL_ERROR("%-13s (#%d) %010u 0x%08X 0x%08X %u\n",
+ desc_lookup(desc), desc, time, data1, data2, line);
+ IWL_ERROR("blink1 blink2 ilink1 ilink2\n");
+ IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
+ ilink1, ilink2);
+
+ iwl_release_nic_access(priv);
+}
+EXPORT_SYMBOL(iwl_dump_nic_error_log);
+
#define EVENT_START_OFFSET (4 * sizeof(u32))

/**
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index a8d062f..e75bf34 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -238,6 +238,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
******************************************************/
void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
u32 num_events, u32 mode);
+void iwl_dump_nic_error_log(struct iwl_priv *priv);
void iwl_dump_nic_event_log(struct iwl_priv *priv);

/*************** DRIVER STATUS FUNCTIONS *****/
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 48c59cb..038eea0 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -2621,76 +2621,6 @@ static inline void iwl4965_disable_interrupts(struct iwl_priv *priv)
IWL_DEBUG_ISR("Disabled interrupts\n");
}

-static const char *desc_lookup(int i)
-{
- switch (i) {
- case 1:
- return "FAIL";
- case 2:
- return "BAD_PARAM";
- case 3:
- return "BAD_CHECKSUM";
- case 4:
- return "NMI_INTERRUPT";
- case 5:
- return "SYSASSERT";
- case 6:
- return "FATAL_ERROR";
- }
-
- return "UNKNOWN";
-}
-
-#define ERROR_START_OFFSET (1 * sizeof(u32))
-#define ERROR_ELEM_SIZE (7 * sizeof(u32))
-
-static void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
-{
- u32 data2, line;
- u32 desc, time, count, base, data1;
- u32 blink1, blink2, ilink1, ilink2;
- int rc;
-
- base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
- return;
- }
-
- rc = iwl_grab_nic_access(priv);
- if (rc) {
- IWL_WARNING("Can not read from adapter at this time.\n");
- return;
- }
-
- count = iwl_read_targ_mem(priv, base);
-
- if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
- IWL_ERROR("Start IWL Error Log Dump:\n");
- IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
- }
-
- desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
- blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
- blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
- ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
- ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
- data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
- data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
- line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
- time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
-
- IWL_ERROR("Desc Time "
- "data1 data2 line\n");
- IWL_ERROR("%-13s (#%d) %010u 0x%08X 0x%08X %u\n",
- desc_lookup(desc), desc, time, data1, data2, line);
- IWL_ERROR("blink1 blink2 ilink1 ilink2\n");
- IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
- ilink1, ilink2);
-
- iwl_release_nic_access(priv);
-}

/**
* iwl4965_irq_handle_error - called for HW or SW error interrupt from card
@@ -2705,7 +2635,7 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)

#ifdef CONFIG_IWLWIFI_DEBUG
if (priv->debug_level & IWL_DL_FW_ERRORS) {
- iwl4965_dump_nic_error_log(priv);
+ iwl_dump_nic_error_log(priv);
iwl_dump_nic_event_log(priv);
iwl4965_print_rx_config_cmd(priv);
}
@@ -5529,20 +5459,6 @@ static ssize_t show_status(struct device *d,

static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);

-static ssize_t dump_error_log(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- char *p = (char *)buf;
-
- if (p[0] == '1')
- iwl4965_dump_nic_error_log((struct iwl_priv *)d->driver_data);
-
- return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
-
/*****************************************************************************
*
* driver setup and teardown
@@ -5588,7 +5504,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)

static struct attribute *iwl4965_sysfs_entries[] = {
&dev_attr_channels.attr,
- &dev_attr_dump_errors.attr,
&dev_attr_flags.attr,
&dev_attr_filter_flags.attr,
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
--
1.5.3.6


2008-05-23 02:11:57

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: move txq_ctx_stop into iwl-tx.c

From: Tomas Winkler <[email protected]>

This patch moves txq_ctx_stop into iwl-tx.c iwlcore module.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 59 +++---------------
drivers/net/wireless/iwlwifi/iwl-5000.c | 32 +++-------
drivers/net/wireless/iwlwifi/iwl-core.h | 2 +-
drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +-
drivers/net/wireless/iwlwifi/iwl-helpers.h | 2 +
drivers/net/wireless/iwlwifi/iwl-prph.h | 5 --
drivers/net/wireless/iwlwifi/iwl-tx.c | 88 ++++++++++++++++++++-------
drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 +-
8 files changed, 88 insertions(+), 104 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index c10ac72..0c3664f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -472,25 +472,13 @@ int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
return ret;
}

-static int iwl4965_disable_tx_fifo(struct iwl_priv *priv)
+/*
+ * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask
+ * must be called under priv->lock and mac access
+ */
+static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask)
{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- ret = iwl_grab_nic_access(priv);
- if (unlikely(ret)) {
- IWL_ERROR("Tx fifo reset failed");
- spin_unlock_irqrestore(&priv->lock, flags);
- return ret;
- }
-
- iwl_write_prph(priv, IWL49_SCD_TXFACT, 0);
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
+ iwl_write_prph(priv, IWL49_SCD_TXFACT, mask);
}

static int iwl4965_apm_init(struct iwl_priv *priv)
@@ -583,36 +571,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}

-/**
- * iwl4965_hw_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory
- */
-void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
-{
-
- int txq_id;
- unsigned long flags;
-
- /* Stop each Tx DMA channel, and wait for it to be idle */
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
- spin_lock_irqsave(&priv->lock, flags);
- if (iwl_grab_nic_access(priv)) {
- spin_unlock_irqrestore(&priv->lock, flags);
- continue;
- }
-
- iwl_write_direct32(priv,
- FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0);
- iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
- FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
- (txq_id), 200);
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
- }
-
- /* Deallocate memory for all Tx queues */
- iwl_hw_txq_ctx_free(priv);
-}
-
static int iwl4965_apm_stop_master(struct iwl_priv *priv)
{
int ret = 0;
@@ -999,8 +957,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv)
(1 << priv->hw_params.max_txq_num) - 1);

/* Activate all Tx DMA/FIFO channels */
- iwl_write_prph(priv, IWL49_SCD_TXFACT,
- SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
+ priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));

iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);

@@ -3626,7 +3583,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.free_shared_mem = iwl4965_free_shared_mem,
.shared_mem_rx_idx = iwl4965_shared_mem_rx_idx,
.txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
- .disable_tx_fifo = iwl4965_disable_tx_fifo,
+ .txq_set_sched = iwl4965_txq_set_sched,
.rx_handler_setup = iwl4965_rx_handler_setup,
.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
.alive_notify = iwl4965_alive_notify,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index d607452..a94cd36 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -662,10 +662,10 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
}

iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK,
- (1 << priv->hw_params.max_txq_num) - 1);
+ IWL_MASK(0, priv->hw_params.max_txq_num));

- iwl_write_prph(priv, IWL50_SCD_TXFACT,
- SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
+ /* Activate all Tx DMA/FIFO channels */
+ priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));

iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
/* map qos queues to fifos one-to-one */
@@ -839,25 +839,13 @@ static u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
}


-static int iwl5000_disable_tx_fifo(struct iwl_priv *priv)
+/*
+ * Activate/Deactivat 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)
{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- ret = iwl_grab_nic_access(priv);
- if (unlikely(ret)) {
- IWL_ERROR("Tx fifo reset failed");
- spin_unlock_irqrestore(&priv->lock, flags);
- return ret;
- }
-
- iwl_write_prph(priv, IWL50_SCD_TXFACT, 0);
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
+ iwl_write_prph(priv, IWL50_SCD_TXFACT, mask);
}

/* Currently 5000 is the supperset of everything */
@@ -894,7 +882,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.free_shared_mem = iwl5000_free_shared_mem,
.shared_mem_rx_idx = iwl5000_shared_mem_rx_idx,
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
- .disable_tx_fifo = iwl5000_disable_tx_fifo,
+ .txq_set_sched = iwl5000_txq_set_sched,
.rx_handler_setup = iwl5000_rx_handler_setup,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
.load_ucode = iwl5000_load_ucode,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 916e0a4..aa22a59 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -110,7 +110,7 @@ struct iwl_lib_ops {
/* setup Rx handler */
void (*rx_handler_setup)(struct iwl_priv *priv);
/* nic Tx fifo handling */
- int (*disable_tx_fifo)(struct iwl_priv *priv);
+ void (*txq_set_sched)(struct iwl_priv *priv, u32 mask);
/* alive notification after init uCode load */
void (*init_alive_start)(struct iwl_priv *priv);
/* alive notification */
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index dfbf728..1fc4d9a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -687,7 +687,7 @@ extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv);
extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv);
extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
-extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv);
+extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl_frame *frame, u8 rate);
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index e4c3f84..dedefa0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -136,6 +136,8 @@ static inline void iwl_set_bits16(__le16 *dst, u8 pos, u8 len, int val)

#define KELVIN_TO_CELSIUS(x) ((x)-273)
#define CELSIUS_TO_KELVIN(x) ((x)+273)
+#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
+

#define IEEE80211_CHAN_W_RADAR_DETECT 0x00000010

diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index d6a04f6..15cb7ff 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -358,11 +358,6 @@
* 7- 0: Enable (1), disable (0), one bit for each channel 0-7
*/
#define IWL49_SCD_TXFACT (IWL49_SCD_START_OFFSET + 0x1c)
-
-/* Mask to enable contiguous Tx DMA/FIFO channels between "lo" and "hi". */
-#define SCD_TXFACT_REG_TXFIFO_MASK(lo, hi) \
- ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
-
/*
* Queue (x) Write Pointers (indexes, really!), one for each Tx queue.
* Initialized and updated by driver as new TFDs are added to queue.
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index f32cdda..f73d690 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -263,24 +263,6 @@ EXPORT_SYMBOL(iwl_queue_space);


/**
- * iwl_hw_txq_ctx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
-{
- int txq_id;
-
- /* Tx queues */
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- iwl_tx_queue_free(priv, &priv->txq[txq_id]);
-
- /* Keep-warm buffer */
- iwl_kw_free(priv);
-}
-EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
-
-/**
* iwl_queue_init - Initialize queue's high/low-water and read/write indexes
*/
static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
@@ -437,6 +419,24 @@ static int iwl_tx_queue_init(struct iwl_priv *priv,

return 0;
}
+/**
+ * iwl_hw_txq_ctx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
+{
+ int txq_id;
+
+ /* Tx queues */
+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+ iwl_tx_queue_free(priv, &priv->txq[txq_id]);
+
+ /* Keep-warm buffer */
+ iwl_kw_free(priv);
+}
+EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
+

/**
* iwl_txq_ctx_reset - Reset TX queue context
@@ -449,6 +449,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
{
int ret = 0;
int txq_id, slots_num;
+ unsigned long flags;

iwl_kw_free(priv);

@@ -461,11 +462,19 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
IWL_ERROR("Keep Warm allocation failed");
goto error_kw;
}
+ spin_lock_irqsave(&priv->lock, flags);
+ ret = iwl_grab_nic_access(priv);
+ if (unlikely(ret)) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ goto error_reset;
+ }

/* Turn off all Tx DMA fifos */
- ret = priv->cfg->ops->lib->disable_tx_fifo(priv);
- if (unlikely(ret))
- goto error_reset;
+ priv->cfg->ops->lib->txq_set_sched(priv, 0);
+
+ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+

/* Tell nic where to find the keep-warm buffer */
ret = iwl_kw_init(priv);
@@ -474,8 +483,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
goto error_reset;
}

- /* Alloc and init all (default 16) Tx queues,
- * including the command queue (#4) */
+ /* Alloc and init all Tx queues, including the command queue (#4) */
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
@@ -496,6 +504,40 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
error_kw:
return ret;
}
+/**
+ * iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory
+ */
+void iwl_txq_ctx_stop(struct iwl_priv *priv)
+{
+
+ int txq_id;
+ unsigned long flags;
+
+
+ /* Turn off all Tx DMA fifos */
+ spin_lock_irqsave(&priv->lock, flags);
+ if (iwl_grab_nic_access(priv)) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return;
+ }
+
+ priv->cfg->ops->lib->txq_set_sched(priv, 0);
+
+ /* Stop each Tx DMA channel, and wait for it to be idle */
+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+ iwl_write_direct32(priv,
+ FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0);
+ iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
+ FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
+ (txq_id), 200);
+ }
+ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* Deallocate memory for all Tx queues */
+ iwl_hw_txq_ctx_free(priv);
+}
+EXPORT_SYMBOL(iwl_txq_ctx_stop);

/*
* handle build REPLY_TX command notification.
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 3cc55ff..14b55ec 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -3412,7 +3412,7 @@ static void __iwl4965_down(struct iwl_priv *priv)
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
spin_unlock_irqrestore(&priv->lock, flags);

- iwl4965_hw_txq_ctx_stop(priv);
+ iwl_txq_ctx_stop(priv);
iwl4965_hw_rxq_stop(priv);

spin_lock_irqsave(&priv->lock, flags);
--
1.5.3.6


2008-05-23 02:11:14

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: move iwl_bcast_addr to iwlcore

From: Tomas Winkler <[email protected]>

This patch renames iwl4965_broadcast_addr to iwl_bcast_addr
and moves it to iwlcore.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +-
drivers/net/wireless/iwlwifi/iwl-core.c | 5 +++++
drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +-
drivers/net/wireless/iwlwifi/iwl4965-base.c | 11 +++++------
4 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 1ec53a3..44215a7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2029,7 +2029,7 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,

frame_size = iwl4965_fill_beacon_frame(priv,
tx_beacon_cmd->frame,
- iwl4965_broadcast_addr,
+ iwl_bcast_addr,
sizeof(frame->u) - sizeof(*tx_beacon_cmd));

BUG_ON(frame_size > MAX_MPDU_SIZE);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 8e411de..79e46c5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -85,6 +85,11 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
};
EXPORT_SYMBOL(iwl_rates);

+
+const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+EXPORT_SYMBOL(iwl_bcast_addr);
+
+
/* This function both allocates and initializes hw and priv. */
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
struct ieee80211_ops *hw_ops)
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 60a8f06..8809fe3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -659,7 +659,7 @@ int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
int iwl4965_init_geos(struct iwl_priv *priv);
void iwl4965_free_geos(struct iwl_priv *priv);

-extern const u8 iwl4965_broadcast_addr[ETH_ALEN];
+extern const u8 iwl_bcast_addr[ETH_ALEN];
int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);

/*
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index edde814..bb820f3 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -207,7 +207,6 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
return index & (q->n_window - 1);
}

-const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

/*************** STATION TABLE MANAGEMENT ****
* mac80211 should be examined to determine if sta_info is duplicating
@@ -692,7 +691,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
}

/* Add the broadcast address so we can send broadcast frames */
- if (iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0) ==
+ if (iwl4965_rxon_add_station(priv, iwl_bcast_addr, 0) ==
IWL_INVALID_STATION) {
IWL_ERROR("Error adding BROADCAST address for transmit.\n");
return -EIO;
@@ -1059,9 +1058,9 @@ static u16 iwl4965_fill_probe_req(struct iwl_priv *priv,
len += 24;

frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
- memcpy(frame->da, iwl4965_broadcast_addr, ETH_ALEN);
+ memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
- memcpy(frame->bssid, iwl4965_broadcast_addr, ETH_ALEN);
+ memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
frame->seq_ctrl = 0;

/* fill in our indirect SSID IE */
@@ -4912,7 +4911,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
/* clear out the station table */
iwlcore_clear_stations_table(priv);

- iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0);
+ iwl4965_rxon_add_station(priv, iwl_bcast_addr, 0);
iwl4965_rxon_add_station(priv, priv->bssid, 0);
iwl4965_rate_scale_init(priv->hw, IWL_STA_ID);
iwl4965_send_beacon_cmd(priv);
@@ -5324,7 +5323,7 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
iwl4965_commit_rxon(priv);
iwl4965_activate_qos(priv, 1);
- iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0);
+ iwl4965_rxon_add_station(priv, iwl_bcast_addr, 0);
}
iwl4965_send_beacon_cmd(priv);

--
1.5.3.6


2008-05-23 02:12:04

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: move iwl_rx_missed_beacon_notif to iwl-rx.c

From: Tomas Winkler <[email protected]>

This patch moves iwl_rx_missed_beacon_notif rx handler to iwl-rx.c.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 22 ----------------------
drivers/net/wireless/iwlwifi/iwl-core.h | 3 +++
drivers/net/wireless/iwlwifi/iwl-rx.c | 22 ++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl4965-base.c | 3 +++
4 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index da08622..8c83384 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2902,26 +2902,7 @@ static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
sizeof(struct iwl4965_rx_phy_res));
}
-static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)

-{
-#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- struct iwl4965_missed_beacon_notif *missed_beacon;
-
- missed_beacon = &pkt->u.missed_beacon;
- if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) {
- IWL_DEBUG_CALIB("missed bcn cnsq %d totl %d rcd %d expctd %d\n",
- le32_to_cpu(missed_beacon->consequtive_missed_beacons),
- le32_to_cpu(missed_beacon->total_missed_becons),
- le32_to_cpu(missed_beacon->num_recvd_beacons),
- le32_to_cpu(missed_beacon->num_expected_beacons));
- if (!test_bit(STATUS_SCANNING, &priv->status))
- iwl_init_sensitivity(priv);
- }
-#endif /*CONFIG_IWL4965_RUN_TIME_CALIB*/
-}
#ifdef CONFIG_IWL4965_HT

/**
@@ -3512,9 +3493,6 @@ static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl4965_rx_reply_rx;

- priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
- iwl4965_rx_missed_beacon_notif;
-
#ifdef CONFIG_IWL4965_HT
priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba;
#endif /* CONFIG_IWL4965_HT */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index aa22a59..eeea4e8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -204,6 +204,9 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
int iwl_rx_queue_restock(struct iwl_priv *priv);
int iwl_rx_queue_space(const struct iwl_rx_queue *q);
void iwl_rx_allocate(struct iwl_priv *priv);
+/* Handlers */
+void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb);

/*****************************************************
* TX
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index ed63e5c..cc61c93 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -33,6 +33,7 @@
#include "iwl-core.h"
#include "iwl-sta.h"
#include "iwl-io.h"
+#include "iwl-calib.h"
#include "iwl-helpers.h"
/************************** RX-FUNCTIONS ****************************/
/*
@@ -446,3 +447,24 @@ int iwl_rxq_stop(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_rxq_stop);

+void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+
+{
+#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ struct iwl4965_missed_beacon_notif *missed_beacon;
+
+ missed_beacon = &pkt->u.missed_beacon;
+ if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) {
+ IWL_DEBUG_CALIB("missed bcn cnsq %d totl %d rcd %d expctd %d\n",
+ le32_to_cpu(missed_beacon->consequtive_missed_beacons),
+ le32_to_cpu(missed_beacon->total_missed_becons),
+ le32_to_cpu(missed_beacon->num_recvd_beacons),
+ le32_to_cpu(missed_beacon->num_expected_beacons));
+ if (!test_bit(STATUS_SCANNING, &priv->status))
+ iwl_init_sensitivity(priv);
+ }
+#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */
+}
+EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 7fe1bb9..1a94574 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -2263,6 +2263,9 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl4965_rx_card_state_notif;
priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;

+ priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
+ iwl_rx_missed_beacon_notif;
+
/* Set up hardware specific Rx handlers */
priv->cfg->ops->lib->rx_handler_setup(priv);
}
--
1.5.3.6


2008-05-23 13:26:45

by Holger Schurig

[permalink] [raw]
Subject: Re: [PATCH 00/51] iwlwifi driver 05/23 updates

> It should be fine as-is, especially since you sent each as a
> reply to the previous.

However, sending LOTS of patches via this way looks funny in
several e-mail clients. Here's an example with KMail:


Attachments:
(No filename) (205.00 B)
staircase.png (20.65 kB)
Download all attachments

2008-05-23 05:44:59

by Harvey Harrison

[permalink] [raw]
Subject: Re: [PATCH] iwlwifi: impelemnt 5000 tx response path

On Fri, 2008-05-23 at 10:09 +0800, Zhu Yi wrote:
> From: Ron Rindjunsky <[email protected]>
>
> This patch implements 5000 HW tx response path
>
> Signed-off-by: Ron Rindjunsky <[email protected]>
> ---
> drivers/net/wireless/iwlwifi/iwl-5000.c | 235 +++++++++++++++++++++++++++++++
> net/mac80211/mlme.c | 10 +-
> 2 files changed, 240 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
> index 685a84e..5d6a28c 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-5000.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
> @@ -972,6 +972,240 @@ static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
> iwl_write_prph(priv, IWL50_SCD_TXFACT, mask);
> }
>
> +
> +static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp)
> +{
> + __le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status +
> + tx_resp->frame_count);
> + return le32_to_cpu(*scd_ssn) & MAX_SN;

How about:

return le32_to_cpup((__le32 *)&tx_resp->status + tx_resp->frame_count);

Cheers,

Harvey


2008-05-23 02:12:00

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: add remove station functionality

From: Tomas Winkler <[email protected]>

This patch adds remove station functionality, which is required for
5000 and AP mode.

There are still some gaps in managment that need to be closed but it
provides sufficient functionality for 5000 HW.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-commands.h | 23 ++++-
drivers/net/wireless/iwlwifi/iwl-dev.h | 1 +
drivers/net/wireless/iwlwifi/iwl-sta.c | 150 +++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-sta.h | 1 +
drivers/net/wireless/iwlwifi/iwl4965-base.c | 44 +--------
5 files changed, 174 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index afd0f7d..a637abe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -928,10 +928,28 @@ struct iwl_addsta_cmd {
/*
* REPLY_ADD_STA = 0x18 (response)
*/
-struct iwl4965_add_sta_resp {
+struct iwl_add_sta_resp {
u8 status; /* ADD_STA_* */
} __attribute__ ((packed));

+#define REM_STA_SUCCESS_MSK 0x1
+/*
+ * REPLY_REM_STA = 0x19 (response)
+ */
+struct iwl_rem_sta_resp {
+ u8 status;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_REM_STA = 0x19 (command)
+ */
+struct iwl_rem_sta_cmd {
+ u8 num_sta; /* number of removed stations */
+ u8 reserved[3];
+ u8 addr[ETH_ALEN]; /* MAC addr of the first station */
+ u8 reserved2[2];
+} __attribute__ ((packed));
+
/*
* REPLY_WEP_KEY = 0x20
*/
@@ -2869,7 +2887,8 @@ struct iwl_rx_packet {
struct iwl_error_resp err_resp;
struct iwl4965_card_state_notif card_state_notif;
struct iwl4965_beacon_notif beacon_status;
- struct iwl4965_add_sta_resp add_sta;
+ struct iwl_add_sta_resp add_sta;
+ struct iwl_rem_sta_resp rem_sta;
struct iwl4965_sleep_notification sleep_notif;
struct iwl4965_spectrum_resp spectrum;
struct iwl4965_notif_statistics stats;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index def1461..d7bca7c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -334,6 +334,7 @@ struct iwl_cmd {
struct iwl_tx_cmd tx;
struct iwl4965_tx_beacon_cmd tx_beacon;
struct iwl4965_rxon_assoc_cmd rxon_assoc;
+ struct iwl_rem_sta_cmd rm_sta;
u8 *indirect;
u8 payload[IWL_CMD_MAX_PAYLOAD];
} __attribute__ ((packed)) cmd;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 99ee1e1..11ec408 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -37,6 +37,10 @@
#include "iwl-io.h"
#include "iwl-helpers.h"

+
+#define IWL_STA_DRIVER_ACTIVE 0x1 /* ucode entry is active */
+#define IWL_STA_UCODE_ACTIVE 0x2 /* ucode entry is active */
+
u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
{
int i;
@@ -241,6 +245,152 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
}
EXPORT_SYMBOL(iwl_add_station_flags);

+
+static int iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
+{
+ unsigned long flags;
+ u8 sta_id;
+ DECLARE_MAC_BUF(mac);
+
+ sta_id = iwl_find_station(priv, addr);
+ if (sta_id != IWL_INVALID_STATION) {
+ IWL_DEBUG_ASSOC("Removed STA from Ucode: %s\n",
+ print_mac(mac, addr));
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
+ memset(&priv->stations[sta_id], 0,
+ sizeof(struct iwl_station_entry));
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int iwl_remove_sta_callback(struct iwl_priv *priv,
+ struct iwl_cmd *cmd, struct sk_buff *skb)
+{
+ struct iwl_rx_packet *res = NULL;
+ const char *addr = cmd->cmd.rm_sta.addr;
+
+ if (!skb) {
+ IWL_ERROR("Error: Response NULL in REPLY_REMOVE_STA.\n");
+ return 1;
+ }
+
+ res = (struct iwl_rx_packet *)skb->data;
+ if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
+ IWL_ERROR("Bad return from REPLY_REMOVE_STA (0x%08X)\n",
+ res->hdr.flags);
+ return 1;
+ }
+
+ switch (res->u.rem_sta.status) {
+ case REM_STA_SUCCESS_MSK:
+ iwl_sta_ucode_deactivate(priv, addr);
+ break;
+ default:
+ 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,
+ u8 flags)
+{
+ struct iwl_rx_packet *res = NULL;
+ int ret;
+
+ struct iwl_rem_sta_cmd rm_sta_cmd;
+
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_REMOVE_STA,
+ .len = sizeof(struct iwl_rem_sta_cmd),
+ .meta.flags = flags,
+ .data = &rm_sta_cmd,
+ };
+
+ memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
+ rm_sta_cmd.num_sta = 1;
+ memcpy(&rm_sta_cmd.addr, addr , ETH_ALEN);
+
+ if (flags & CMD_ASYNC)
+ cmd.meta.u.callback = iwl_remove_sta_callback;
+ else
+ cmd.meta.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;
+ if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
+ IWL_ERROR("Bad return from REPLY_REMOVE_STA (0x%08X)\n",
+ res->hdr.flags);
+ ret = -EIO;
+ }
+
+ if (!ret) {
+ switch (res->u.rem_sta.status) {
+ case REM_STA_SUCCESS_MSK:
+ iwl_sta_ucode_deactivate(priv, addr);
+ IWL_DEBUG_ASSOC("REPLY_REMOVE_STA PASSED\n");
+ break;
+ default:
+ ret = -EIO;
+ IWL_ERROR("REPLY_REMOVE_STA failed\n");
+ break;
+ }
+ }
+
+ priv->alloc_rxb_skb--;
+ dev_kfree_skb_any(cmd.meta.u.skb);
+
+ return ret;
+}
+/**
+ * iwl_remove_station - Remove driver's knowledge of station.
+ *
+ */
+u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+{
+ int index = IWL_INVALID_STATION;
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ if (is_ap)
+ index = IWL_AP_ID;
+ else if (is_broadcast_ether_addr(addr))
+ index = priv->hw_params.bcast_sta_id;
+ else
+ for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
+ if (priv->stations[i].used &&
+ !compare_ether_addr(priv->stations[i].sta.sta.addr,
+ addr)) {
+ index = i;
+ break;
+ }
+
+ if (unlikely(index == IWL_INVALID_STATION))
+ goto out;
+
+ if (priv->stations[index].used) {
+ priv->stations[index].used = 0;
+ priv->num_stations--;
+ }
+
+ BUG_ON(priv->num_stations < 0);
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+ iwl_send_remove_station(priv, addr, CMD_ASYNC);
+ return index;
+out:
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(iwl_remove_station);
int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
{
int i;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index b643546..500e1df 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -43,5 +43,6 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
int iwl_remove_dynamic_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key, u8 sta_id);
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
+u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
#endif /* __iwl_sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index b47d8be..ea622db 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -140,49 +140,6 @@ static const char *iwl4965_escape_essid(const char *essid, u8 essid_len)

/**************************************************************/

-#if 0 /* temporary disable till we add real remove station */
-/**
- * iwl4965_remove_station - Remove driver's knowledge of station.
- *
- * NOTE: This does not remove station from device's station table.
- */
-static u8 iwl4965_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
-{
- int index = IWL_INVALID_STATION;
- int i;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- if (is_ap)
- index = IWL_AP_ID;
- else if (is_broadcast_ether_addr(addr))
- index = priv->hw_params.bcast_sta_id;
- else
- for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
- if (priv->stations[i].used &&
- !compare_ether_addr(priv->stations[i].sta.sta.addr,
- addr)) {
- index = i;
- break;
- }
-
- if (unlikely(index == IWL_INVALID_STATION))
- goto out;
-
- if (priv->stations[index].used) {
- priv->stations[index].used = 0;
- priv->num_stations--;
- }
-
- BUG_ON(priv->num_stations < 0);
-
-out:
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
-}
-#endif
-


static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
@@ -404,6 +361,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
return rc;
}

+ iwl_remove_station(priv, iwl_bcast_addr, 0);
iwlcore_clear_stations_table(priv);

if (!priv->error_recovering)
--
1.5.3.6


2008-05-23 02:11:25

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: add rx_handlers stub for iwl5000

From: Ron Rindjunsky <[email protected]>

This patch adds rx_handler_setup stub to iwl5000.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-5000.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index d155247..00ad360 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -464,6 +464,10 @@ static u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len)
return len;
}

+static void iwl5000_rx_handler_setup(struct iwl_priv *priv)
+{
+}
+
static struct iwl_hcmd_ops iwl5000_hcmd = {
};

@@ -483,6 +487,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.shared_mem_rx_idx = iwl5000_shared_mem_rx_idx,
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
.disable_tx_fifo = iwl5000_disable_tx_fifo,
+ .rx_handler_setup = iwl5000_rx_handler_setup,
.apm_ops = {
.init = iwl5000_apm_init,
.config = iwl5000_nic_config,
--
1.5.3.6


2008-05-23 02:11:43

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: create drivers debugfs dir under wiphy->debugfsdir

This patch creates driver's debugfs tree under wiphy->debugfsdir.
This patch fixes collision in debugfs if two or more NICs are plugged.

Signed-off-by: Zhu Yi <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-debugfs.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index c64e602..29e16ba 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -367,6 +367,7 @@ DEBUGFS_READ_FILE_OPS(tx_statistics);
int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
{
struct iwl_debugfs *dbgfs;
+ struct dentry *phyd = priv->hw->wiphy->debugfsdir;

dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
if (!dbgfs) {
@@ -375,7 +376,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)

priv->dbgfs = dbgfs;
dbgfs->name = name;
- dbgfs->dir_drv = debugfs_create_dir(name, NULL);
+ dbgfs->dir_drv = debugfs_create_dir(name, phyd);
if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)){
goto err;
}
--
1.5.3.6


2008-05-23 02:12:08

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: add iwl5000_tx_response structure

From: Ron Rindjunsky <[email protected]>

This patch adds iwl5000_tx_repsons structure.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-commands.h | 48 ++++++++++++++++++++++++---
1 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 6f62beb..bad0e94 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -1419,6 +1419,11 @@ enum {
* within the sending station (this 4965), rather than whether it was
* received successfully by the destination station.
*/
+struct agg_tx_status {
+ __le16 status;
+ __le16 sequence;
+} __attribute__ ((packed));
+
struct iwl4965_tx_resp {
u8 frame_count; /* 1 no aggregation, >1 aggregation */
u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */
@@ -1453,11 +1458,6 @@ struct iwl4965_tx_resp {
__le32 status; /* TX status (for aggregation status of 1st frame) */
} __attribute__ ((packed));

-struct agg_tx_status {
- __le16 status;
- __le16 sequence;
-} __attribute__ ((packed));
-
struct iwl4965_tx_resp_agg {
u8 frame_count; /* 1 no aggregation, >1 aggregation */
u8 reserved1;
@@ -1472,6 +1472,44 @@ struct iwl4965_tx_resp_agg {
/* of 1st frame) */
} __attribute__ ((packed));

+struct iwl5000_tx_resp {
+ u8 frame_count; /* 1 no aggregation, >1 aggregation */
+ u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */
+ u8 failure_rts; /* # failures due to unsuccessful RTS */
+ u8 failure_frame; /* # failures due to no ACK (unused for agg) */
+
+ /* For non-agg: Rate at which frame was successful.
+ * For agg: Rate at which all frames were transmitted. */
+ __le32 rate_n_flags; /* RATE_MCS_* */
+
+ /* For non-agg: RTS + CTS + frame tx attempts time + ACK.
+ * For agg: RTS + CTS + aggregation tx time + block-ack time. */
+ __le16 wireless_media_time; /* uSecs */
+
+ __le16 reserved;
+ __le32 pa_power1; /* RF power amplifier measurement (not used) */
+ __le32 pa_power2;
+
+ __le32 tfd_info;
+ __le16 seq_ctl;
+ __le16 byte_cnt;
+ __le32 tlc_info;
+ /*
+ * For non-agg: frame status TX_STATUS_*
+ * For agg: status of 1st frame, AGG_TX_STATE_*; other frame status
+ * fields follow this one, up to frame_count.
+ * Bit fields:
+ * 11- 0: AGG_TX_STATE_* status code
+ * 15-12: Retry count for 1st frame in aggregation (retries
+ * occur if tx failed for this frame when it was a
+ * member of a previous aggregation block). If rate
+ * scaling is used, retry count indicates the rate
+ * table entry used for all frames in the new agg.
+ * 31-16: Sequence # for this frame's Tx cmd (not SSN!)
+ */
+ struct agg_tx_status status; /* TX status (in aggregation -
+ * status of 1st frame) */
+} __attribute__ ((packed));
/*
* REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
*
--
1.5.3.6


2008-05-23 02:11:42

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: increase max payload of iwl_cmd

From: Ron Rindjunsky <[email protected]>

This patch increases iwl_cmd payload maximum size from 360 to 640
to fit some of iwl5000 commands as well.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 820542b..b61c647 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -308,6 +308,8 @@ struct iwl_cmd_meta {

} __attribute__ ((packed));

+#define IWL_CMD_MAX_PAYLOAD 640
+
/**
* struct iwl_cmd
*
@@ -333,7 +335,7 @@ struct iwl_cmd {
struct iwl4965_tx_beacon_cmd tx_beacon;
struct iwl4965_rxon_assoc_cmd rxon_assoc;
u8 *indirect;
- u8 payload[360];
+ u8 payload[IWL_CMD_MAX_PAYLOAD];
} __attribute__ ((packed)) cmd;
} __attribute__ ((packed));

--
1.5.3.6


2008-05-23 02:11:40

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: use uCode error and event tables pointer w.r.t loaded image

From: Gregory Greenman <[email protected]>

This patch updates the usage of the pointers to error and log tables
received in alive response w.r.t. the current uCode image.

Signed-off-by: Gregory Greenman <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-core.c | 29 +++++++++++++++++++----------
1 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 785396f..373e984 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1084,17 +1084,20 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
u32 data2, line;
u32 desc, time, count, base, data1;
u32 blink1, blink2, ilink1, ilink2;
- int rc;
+ int ret;

- base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.error_event_table_ptr);

if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
return;
}

- rc = iwl_grab_nic_access(priv);
- if (rc) {
+ ret = iwl_grab_nic_access(priv);
+ if (ret) {
IWL_WARNING("Can not read from adapter at this time.\n");
return;
}
@@ -1146,8 +1149,10 @@ void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,

if (num_events == 0)
return;
-
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);

if (mode == 0)
event_size = 2 * sizeof(u32);
@@ -1177,7 +1182,7 @@ EXPORT_SYMBOL(iwl_print_event_log);

void iwl_dump_nic_event_log(struct iwl_priv *priv)
{
- int rc;
+ int ret;
u32 base; /* SRAM byte address of event log header */
u32 capacity; /* event log capacity in # entries */
u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
@@ -1185,14 +1190,18 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
u32 next_entry; /* index of next entry to be written by uCode */
u32 size; /* # entries that we'll print */

- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
return;
}

- rc = iwl_grab_nic_access(priv);
- if (rc) {
+ ret = iwl_grab_nic_access(priv);
+ if (ret) {
IWL_WARNING("Can not read from adapter at this time.\n");
return;
}
--
1.5.3.6


2008-05-23 02:12:07

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: activate status ready timeout only for run time ucode

From: Ron Rindjunsky <[email protected]>

This patch makes driver state timeout checks on ucode alive response
only if run time ucode have been loaded.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 6 ++----
drivers/net/wireless/iwlwifi/iwl-5000.c | 5 ++++-
drivers/net/wireless/iwlwifi/iwl4965-base.c | 26 ++++++++++++++------------
3 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 8c83384..d657b43 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -156,6 +156,8 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)

IWL_DEBUG_INFO("Begin load bsm\n");

+ priv->ucode_type = UCODE_RT;
+
/* make sure bootstrap program is no larger than BSM's SRAM size */
if (len > IWL_MAX_BSM_SIZE)
return -EINVAL;
@@ -221,8 +223,6 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)

iwl_release_nic_access(priv);

- priv->ucode_type = UCODE_INIT;
-
return 0;
}

@@ -269,8 +269,6 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)

IWL_DEBUG_INFO("Runtime uCode pointers are set.\n");

- priv->ucode_type = UCODE_RT;
-
return ret;
}

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index eb6141e..685a84e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -804,8 +804,11 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)

iwl5000_send_Xtal_calib(priv);

- if (priv->ucode_type == UCODE_RT)
+ if (priv->ucode_type == UCODE_RT) {
iwl5000_send_calib_results(priv);
+ set_bit(STATUS_READY, &priv->status);
+ priv->is_open = 1;
+ }

return 0;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 1a94574..e46bdb1 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -4082,21 +4082,23 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw)
if (test_bit(STATUS_IN_SUSPEND, &priv->status))
return 0;

- /* Wait for START_ALIVE from ucode. Otherwise callbacks from
+ /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
* mac80211 will not be run successfully. */
- ret = wait_event_interruptible_timeout(priv->wait_command_queue,
- test_bit(STATUS_READY, &priv->status),
- UCODE_READY_TIMEOUT);
- if (!ret) {
- if (!test_bit(STATUS_READY, &priv->status)) {
- IWL_ERROR("Wait for START_ALIVE timeout after %dms.\n",
- jiffies_to_msecs(UCODE_READY_TIMEOUT));
- ret = -ETIMEDOUT;
- goto out_release_irq;
+ if (priv->ucode_type == UCODE_RT) {
+ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+ test_bit(STATUS_READY, &priv->status),
+ UCODE_READY_TIMEOUT);
+ if (!ret) {
+ if (!test_bit(STATUS_READY, &priv->status)) {
+ IWL_ERROR("START_ALIVE timeout after %dms.\n",
+ jiffies_to_msecs(UCODE_READY_TIMEOUT));
+ ret = -ETIMEDOUT;
+ goto out_release_irq;
+ }
}
- }

- priv->is_open = 1;
+ priv->is_open = 1;
+ }
IWL_DEBUG_MAC80211("leave\n");
return 0;

--
1.5.3.6


2008-05-23 02:11:33

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: remove 4965 remainings in iwl-eeprom.c file

From: Tomas Winkler <[email protected]>

The patch cleans up 4965 remaings from iwl-eeprom.c file.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-eeprom.c | 22 +++++++++++-----------
1 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index fa30660..300ef8e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -365,11 +365,11 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
? # x " " : "")

/**
- * iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv.
+ * iwl_set_fat_chan_info - Copy fat channel info into driver's priv.
*
* Does not set up a command, or touch hardware.
*/
-static int iwl4965_set_fat_chan_info(struct iwl_priv *priv,
+static int iwl_set_fat_chan_info(struct iwl_priv *priv,
enum ieee80211_band band, u16 channel,
const struct iwl_eeprom_channel *eeprom_ch,
u8 fat_extension_channel)
@@ -542,16 +542,16 @@ int iwl_init_channel_map(struct iwl_priv *priv)
fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE;

/* Set up driver's info for lower half */
- iwl4965_set_fat_chan_info(priv, ieeeband,
- eeprom_ch_index[ch],
- &(eeprom_ch_info[ch]),
- fat_extension_chan);
+ iwl_set_fat_chan_info(priv, ieeeband,
+ eeprom_ch_index[ch],
+ &(eeprom_ch_info[ch]),
+ fat_extension_chan);

/* Set up driver's info for upper half */
- iwl4965_set_fat_chan_info(priv, ieeeband,
- (eeprom_ch_index[ch] + 4),
- &(eeprom_ch_info[ch]),
- HT_IE_EXT_CHANNEL_BELOW);
+ iwl_set_fat_chan_info(priv, ieeeband,
+ (eeprom_ch_index[ch] + 4),
+ &(eeprom_ch_info[ch]),
+ HT_IE_EXT_CHANNEL_BELOW);
}
}

@@ -560,7 +560,7 @@ int iwl_init_channel_map(struct iwl_priv *priv)
EXPORT_SYMBOL(iwl_init_channel_map);

/*
- * iwl_free_channel_map - undo allocations in iwl4965_init_channel_map
+ * iwl_free_channel_map - undo allocations in iwl_init_channel_map
*/
void iwl_free_channel_map(struct iwl_priv *priv)
{
--
1.5.3.6


2008-05-23 02:11:50

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: remove 4965 from alive_resp structures

From: Tomas Winkler <[email protected]>

This patch removes 4965 from alive_resp and init_alivie_resp.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-commands.h | 10 +++++-----
drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ++--
drivers/net/wireless/iwlwifi/iwl4965-base.c | 16 ++++++++--------
3 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 5b9e9bf..afd0f7d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -373,7 +373,7 @@ struct iwl4965_tx_power_db {
* 3) Tx gain compensation to balance 4965's 2 Tx chains for MIMO operation,
* for each of 5 frequency ranges.
*/
-struct iwl4965_init_alive_resp {
+struct iwl_init_alive_resp {
u8 ucode_minor;
u8 ucode_major;
__le16 reserved1;
@@ -449,7 +449,7 @@ struct iwl4965_init_alive_resp {
* The Linux driver can print both logs to the system log when a uCode error
* occurs.
*/
-struct iwl4965_alive_resp {
+struct iwl_alive_resp {
u8 ucode_minor;
u8 ucode_major;
__le16 reserved1;
@@ -473,7 +473,7 @@ union tsf {
/*
* REPLY_ERROR = 0x2 (response only, not a command)
*/
-struct iwl4965_error_resp {
+struct iwl_error_resp {
__le32 error_type;
u8 cmd_id;
u8 reserved1;
@@ -2861,12 +2861,12 @@ struct iwl_rx_packet {
__le32 len;
struct iwl_cmd_header hdr;
union {
- struct iwl4965_alive_resp alive_frame;
+ struct iwl_alive_resp alive_frame;
struct iwl4965_rx_frame rx_frame;
struct iwl4965_tx_resp tx_resp;
struct iwl4965_spectrum_notification spectrum_notif;
struct iwl4965_csa_notification csa_notif;
- struct iwl4965_error_resp err_resp;
+ struct iwl_error_resp err_resp;
struct iwl4965_card_state_notif card_state_notif;
struct iwl4965_beacon_notif beacon_status;
struct iwl4965_add_sta_resp add_sta;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index ea08cf9..4c31164 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1036,8 +1036,8 @@ struct iwl_priv {

/* 1st responses from initialize and runtime uCode images.
* 4965's initialize alive response contains some calibration data. */
- struct iwl4965_init_alive_resp card_alive_init;
- struct iwl4965_alive_resp card_alive;
+ struct iwl_init_alive_resp card_alive_init;
+ struct iwl_alive_resp card_alive;
#ifdef CONFIG_IWLWIFI_RFKILL
struct iwl_rfkill_mngr rfkill_mngr;
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 0559cdc..857ec37 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1935,11 +1935,11 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
}


-static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl_rx_reply_alive(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- struct iwl4965_alive_resp *palive;
+ struct iwl_alive_resp *palive;
struct delayed_work *pwork;

palive = &pkt->u.alive_frame;
@@ -1953,12 +1953,12 @@ static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
IWL_DEBUG_INFO("Initialization Alive received.\n");
memcpy(&priv->card_alive_init,
&pkt->u.alive_frame,
- sizeof(struct iwl4965_init_alive_resp));
+ sizeof(struct iwl_init_alive_resp));
pwork = &priv->init_alive_start;
} else {
IWL_DEBUG_INFO("Runtime Alive received.\n");
memcpy(&priv->card_alive, &pkt->u.alive_frame,
- sizeof(struct iwl4965_alive_resp));
+ sizeof(struct iwl_alive_resp));
pwork = &priv->alive_start;
}

@@ -2287,7 +2287,7 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
*/
static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
{
- priv->rx_handlers[REPLY_ALIVE] = iwl4965_rx_reply_alive;
+ priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
priv->rx_handlers[REPLY_ADD_STA] = iwl4965_rx_reply_add_sta;
priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error;
priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl4965_rx_csa;
@@ -3431,7 +3431,7 @@ static void __iwl4965_down(struct iwl_priv *priv)
priv->cfg->ops->lib->free_shared_mem(priv);

exit:
- memset(&priv->card_alive, 0, sizeof(struct iwl4965_alive_resp));
+ memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));

if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);
@@ -5085,7 +5085,7 @@ static ssize_t show_version(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = d->driver_data;
- struct iwl4965_alive_resp *palive = &priv->card_alive;
+ struct iwl_alive_resp *palive = &priv->card_alive;

if (palive->is_valid)
return sprintf(buf, "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
--
1.5.3.6


2008-05-23 02:11:49

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: clean up alive_start routine

From: Tomas Winkler <[email protected]>

This patch cleans up alive_start routine. It removes 4965 from the common
code and moves the run time calibration reset into a common code.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 12 ------------
drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ----
drivers/net/wireless/iwlwifi/iwl-calib.c | 18 ++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-calib.h | 5 ++++-
drivers/net/wireless/iwlwifi/iwl4965-base.c | 19 ++++++++++---------
5 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index c92742c..547287c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -925,15 +925,6 @@ int iwl4965_alive_notify(struct iwl_priv *priv)

spin_lock_irqsave(&priv->lock, flags);

-#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
- memset(&(priv->sensitivity_data), 0,
- sizeof(struct iwl_sensitivity_data));
- memset(&(priv->chain_noise_data), 0,
- sizeof(struct iwl_chain_noise_data));
- for (i = 0; i < NUM_RX_CHAINS; i++)
- priv->chain_noise_data.delta_gain_code[i] =
- CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
-#endif /* CONFIG_IWL4965_RUN_TIME_CALIB*/
ret = iwl_grab_nic_access(priv);
if (ret) {
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1000,9 +991,6 @@ int iwl4965_alive_notify(struct iwl_priv *priv)
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);

- /* Ask for statistics now, the uCode will send statistics notification
- * periodically after association */
- iwl_send_statistics_request(priv, CMD_ASYNC);
return ret;
}

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index d6ffdee..0355ccd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -580,10 +580,6 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)

iwl5000_send_wimax_coex(priv);

- /* Ask for statistics now, the uCode will send notification
- * periodically after association */
- iwl_send_statistics_request(priv, CMD_ASYNC);
-
return 0;
}

diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index beb9716..a6c7f0d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -786,3 +786,21 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_chain_noise_calibration);

+
+void iwl_reset_run_time_calib(struct iwl_priv *priv)
+{
+ int i;
+ memset(&(priv->sensitivity_data), 0,
+ sizeof(struct iwl_sensitivity_data));
+ memset(&(priv->chain_noise_data), 0,
+ sizeof(struct iwl_chain_noise_data));
+ for (i = 0; i < NUM_RX_CHAINS; i++)
+ priv->chain_noise_data.delta_gain_code[i] =
+ CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
+
+ /* Ask for statistics now, the uCode will send notification
+ * periodically after association */
+ iwl_send_statistics_request(priv, CMD_ASYNC);
+}
+EXPORT_SYMBOL(iwl_reset_run_time_calib);
+
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h
index e690668..b8e57c5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.h
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.h
@@ -78,7 +78,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv,
struct iwl4965_notif_statistics *resp);

void iwl_init_sensitivity(struct iwl_priv *priv);
-
+void iwl_reset_run_time_calib(struct iwl_priv *priv);
static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
{

@@ -101,6 +101,9 @@ static inline void iwl_init_sensitivity(struct iwl_priv *priv)
static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
{
}
+static inline void iwl_reset_run_time_calib(struct iwl_priv *priv)
+{
+}
#endif

#endif /* __iwl_calib_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 89dd890..0559cdc 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -3252,11 +3252,11 @@ static int iwl4965_read_ucode(struct iwl_priv *priv)
}

/**
- * iwl4965_alive_start - called after REPLY_ALIVE notification received
+ * iwl_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
- * Alive gets handled by iwl4965_init_alive_start()).
+ * Alive gets handled by iwl_init_alive_start()).
*/
-static void iwl4965_alive_start(struct iwl_priv *priv)
+static void iwl_alive_start(struct iwl_priv *priv)
{
int ret = 0;

@@ -3280,7 +3280,6 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
}

iwlcore_clear_stations_table(priv);
-
ret = priv->cfg->ops->lib->alive_notify(priv);
if (ret) {
IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
@@ -3318,6 +3317,8 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
/* Configure Bluetooth device coexistence support */
iwl4965_send_bt_config(priv);

+ iwl_reset_run_time_calib(priv);
+
/* Configure the adapter for unassociated operation */
iwl4965_commit_rxon(priv);

@@ -3562,7 +3563,7 @@ static int __iwl4965_up(struct iwl_priv *priv)
*
*****************************************************************************/

-static void iwl4965_bg_init_alive_start(struct work_struct *data)
+static void iwl_bg_init_alive_start(struct work_struct *data)
{
struct iwl_priv *priv =
container_of(data, struct iwl_priv, init_alive_start.work);
@@ -3575,7 +3576,7 @@ static void iwl4965_bg_init_alive_start(struct work_struct *data)
mutex_unlock(&priv->mutex);
}

-static void iwl4965_bg_alive_start(struct work_struct *data)
+static void iwl_bg_alive_start(struct work_struct *data)
{
struct iwl_priv *priv =
container_of(data, struct iwl_priv, alive_start.work);
@@ -3584,7 +3585,7 @@ static void iwl4965_bg_alive_start(struct work_struct *data)
return;

mutex_lock(&priv->mutex);
- iwl4965_alive_start(priv);
+ iwl_alive_start(priv);
mutex_unlock(&priv->mutex);
}

@@ -5476,8 +5477,8 @@ static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update);
INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor);
INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate);
- INIT_DELAYED_WORK(&priv->init_alive_start, iwl4965_bg_init_alive_start);
- INIT_DELAYED_WORK(&priv->alive_start, iwl4965_bg_alive_start);
+ INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
+ INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
INIT_DELAYED_WORK(&priv->scan_check, iwl4965_bg_scan_check);

iwl4965_hw_setup_deferred_work(priv);
--
1.5.3.6


2008-05-23 02:11:24

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: rename and move Tx queue activation/deactivation

From: Ron Rindjunsky <[email protected]>

This patch moves iwl4965_txq_ctx_activate and iwl4965_txq_ctx_deactivate
to iwl-dev.h and removes 4965 prefix from their names.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 14 ++------------
drivers/net/wireless/iwlwifi/iwl-dev.h | 10 ++++++++++
2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 52c7eae..f848a5b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -911,16 +911,6 @@ static const u16 default_queue_to_tx_fifo[] = {
IWL_TX_FIFO_HCCA_2
};

-static inline void iwl4965_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
-{
- set_bit(txq_id, &priv->txq_ctx_active_msk);
-}
-
-static inline void iwl4965_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
-{
- clear_bit(txq_id, &priv->txq_ctx_active_msk);
-}
-
int iwl4965_alive_notify(struct iwl_priv *priv)
{
u32 a;
@@ -998,7 +988,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv)
/* Map each Tx/cmd queue to its corresponding fifo */
for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
int ac = default_queue_to_tx_fifo[i];
- iwl4965_txq_ctx_activate(priv, i);
+ iwl_txq_ctx_activate(priv, i);
iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
}

@@ -3115,7 +3105,7 @@ static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id,
iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);

iwl_clear_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
- iwl4965_txq_ctx_deactivate(priv, txq_id);
+ iwl_txq_ctx_deactivate(priv, txq_id);
iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);

iwl_release_nic_access(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 305491f..533479e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1210,6 +1210,16 @@ struct iwl_priv {
struct timer_list statistics_periodic;
}; /*iwl_priv */

+static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
+{
+ set_bit(txq_id, &priv->txq_ctx_active_msk);
+}
+
+static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
+{
+ clear_bit(txq_id, &priv->txq_ctx_active_msk);
+}
+
static inline int iwl_is_associated(struct iwl_priv *priv)
{
return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
--
1.5.3.6


2008-05-23 02:11:10

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: rename iwl4965_queue to iwl_queue

From: Tomas Winkler <[email protected]>

This patch renames iwl4965_queue to iwl_queue.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 16 ++------------
drivers/net/wireless/iwlwifi/iwl-dev.h | 6 ++--
drivers/net/wireless/iwlwifi/iwl-tx.c | 4 +-
drivers/net/wireless/iwlwifi/iwl4965-base.c | 28 +++++++++++++-------------
4 files changed, 22 insertions(+), 32 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 17847f9..2bb0075 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -3231,7 +3231,7 @@ static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id,
int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
u8 tid, int txq_id)
{
- struct iwl4965_queue *q = &priv->txq[txq_id].q;
+ struct iwl_queue *q = &priv->txq[txq_id].q;
u8 *addr = priv->stations[sta_id].sta.sta.addr;
struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];

@@ -3263,16 +3263,6 @@ int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
}

/**
- * iwl4965_queue_dec_wrap - Decrement queue index, wrap back to end if needed
- * @index -- current index
- * @n_bd -- total number of entries in queue (s/b power of 2)
- */
-static inline int iwl4965_queue_dec_wrap(int index, int n_bd)
-{
- return (index == 0) ? n_bd - 1 : index - 1;
-}
-
-/**
* iwl4965_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA
*
* Handles block-acknowledge notification from device, which reports success
@@ -3304,7 +3294,7 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg;

/* Find index just before block-ack window */
- index = iwl4965_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
+ index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);

/* TODO: Need to get this copy more safely - now good for debug */

@@ -3337,7 +3327,7 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
int freed = iwl4965_tx_queue_reclaim(priv, scd_flow, index);
priv->stations[ba_resp->sta_id].
tid[ba_resp->tid].tfds_in_queue -= freed;
- if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
+ if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
priv->mac80211_registered &&
agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
ieee80211_wake_queue(priv->hw, ampdu_q);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 5dccc5a..cf99224 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -102,7 +102,7 @@ struct iwl_rx_mem_buffer {
*
* Contains common data for Rx and Tx queues
*/
-struct iwl4965_queue {
+struct iwl_queue {
int n_bd; /* number of BDs in this queue */
int write_ptr; /* 1-st empty entry (index) host_w*/
int read_ptr; /* last used entry (index) host_r*/
@@ -137,7 +137,7 @@ struct iwl4965_tx_info {
* descriptors) and required locking structures.
*/
struct iwl_tx_queue {
- struct iwl4965_queue q;
+ struct iwl_queue q;
struct iwl_tfd_frame *bd;
struct iwl_cmd *cmd;
dma_addr_t dma_addr_cmd;
@@ -721,7 +721,7 @@ extern u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid);

extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel);
extern int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
-extern int iwl4965_queue_space(const struct iwl4965_queue *q);
+extern int iwl_queue_space(const struct iwl_queue *q);
struct iwl_priv;

extern void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index a1e03cc..870d257 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -105,7 +105,7 @@ EXPORT_SYMBOL(iwl_hw_txq_free_tfd);
*/
static void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
{
- struct iwl4965_queue *q = &txq->q;
+ struct iwl_queue *q = &txq->q;
struct pci_dev *dev = priv->pci_dev;
int len;

@@ -158,7 +158,7 @@ EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
/**
* iwl_queue_init - Initialize queue's high/low-water and read/write indexes
*/
-static int iwl_queue_init(struct iwl_priv *priv, struct iwl4965_queue *q,
+static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
int count, int slots_num, u32 id)
{
q->n_bd = count;
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index c713b27..2e7e616 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -173,7 +173,7 @@ static const char *iwl4965_escape_essid(const char *essid, u8 essid_len)
* See more detailed info in iwl-4965-hw.h.
***************************************************/

-int iwl4965_queue_space(const struct iwl4965_queue *q)
+int iwl_queue_space(const struct iwl_queue *q)
{
int s = q->read_ptr - q->write_ptr;

@@ -190,14 +190,14 @@ int iwl4965_queue_space(const struct iwl4965_queue *q)
}


-static inline int x2_queue_used(const struct iwl4965_queue *q, int i)
+static inline int iwl_queue_used(const struct iwl_queue *q, int i)
{
return q->write_ptr > q->read_ptr ?
(i >= q->read_ptr && i < q->write_ptr) :
!(i < q->read_ptr && i >= q->write_ptr);
}

-static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge)
+static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
{
/* This is for scan command, the big buffer at end of command array */
if (is_huge)
@@ -348,7 +348,7 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
- struct iwl4965_queue *q = &txq->q;
+ struct iwl_queue *q = &txq->q;
struct iwl_tfd_frame *tfd;
u32 *control_flags;
struct iwl_cmd *out_cmd;
@@ -369,7 +369,7 @@ int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
return -EIO;
}

- if (iwl4965_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
+ if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
IWL_ERROR("No space for Tx\n");
return -ENOSPC;
}
@@ -1768,7 +1768,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
u32 *control_flags;
int txq_id = ctl->queue;
struct iwl_tx_queue *txq = NULL;
- struct iwl4965_queue *q = NULL;
+ struct iwl_queue *q = NULL;
dma_addr_t phys_addr;
dma_addr_t txcmd_phys;
dma_addr_t scratch_phys;
@@ -1981,7 +1981,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
if (rc)
return rc;

- if ((iwl4965_queue_space(q) < q->high_mark)
+ if ((iwl_queue_space(q) < q->high_mark)
&& priv->mac80211_registered) {
if (wait_write_ptr) {
spin_lock_irqsave(&priv->lock, flags);
@@ -2332,10 +2332,10 @@ static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv,
int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
{
struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct iwl4965_queue *q = &txq->q;
+ struct iwl_queue *q = &txq->q;
int nfreed = 0;

- if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) {
+ if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
"is out of range [0-%d] %d %d.\n", txq_id,
index, q->n_bd, q->write_ptr, q->read_ptr);
@@ -2541,7 +2541,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
__le16 *qc;
#endif

- if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
+ if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
"is out of range [0-%d] %d %d\n", txq_id,
index, txq->q.n_bd, txq->q.write_ptr,
@@ -2587,7 +2587,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;

- if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
+ if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
txq_id >= 0 && priv->mac80211_registered &&
agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
/* calculate mac80211 ampdu sw queue to wake */
@@ -2621,7 +2621,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
if (tid != MAX_TID_COUNT)
priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
- if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
+ if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
(txq_id >= 0) && priv->mac80211_registered)
ieee80211_wake_queue(priv->hw, txq_id);
if (tid != MAX_TID_COUNT)
@@ -5783,7 +5783,7 @@ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
struct iwl_priv *priv = hw->priv;
int i, avail;
struct iwl_tx_queue *txq;
- struct iwl4965_queue *q;
+ struct iwl_queue *q;
unsigned long flags;

IWL_DEBUG_MAC80211("enter\n");
@@ -5798,7 +5798,7 @@ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
for (i = 0; i < AC_NUM; i++) {
txq = &priv->txq[i];
q = &txq->q;
- avail = iwl4965_queue_space(q);
+ avail = iwl_queue_space(q);

stats[i].len = q->n_window - avail;
stats[i].limit = q->n_window - q->high_mark;
--
1.5.3.6


2008-05-23 02:11:17

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: refactor ieee80211_get_qos_ctrl

From: Tomas Winkler <[email protected]>

This patch refactors ieee80211_get_qos_ctrl function and its usage
in iwlwifi drivers. Function is moved as inline into iwl-helpers.h.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 17 +++++----
drivers/net/wireless/iwlwifi/iwl-dev.h | 1 -
drivers/net/wireless/iwlwifi/iwl-helpers.h | 19 ++++++++++
drivers/net/wireless/iwlwifi/iwl3945-base.c | 35 +++++++-----------
drivers/net/wireless/iwlwifi/iwl4965-base.c | 51 +++++++++++---------------
5 files changed, 63 insertions(+), 60 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index ce70f2b..071c7b6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -282,14 +282,20 @@ static void rs_tl_rm_old_stats(struct iwl4965_traffic_load *tl, u32 curr_time)
* increment traffic load value for tid and also remove
* any old values if passed the certain time period
*/
-static void rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, u8 tid)
+static void rs_tl_add_packet(struct iwl4965_lq_sta *lq_data,
+ struct ieee80211_hdr *hdr)
{
u32 curr_time = jiffies_to_msecs(jiffies);
u32 time_diff;
s32 index;
struct iwl4965_traffic_load *tl = NULL;
+ u16 fc = le16_to_cpu(hdr->frame_control);
+ u8 tid;

- if (tid >= TID_MAX_LOAD_COUNT)
+ if (ieee80211_is_qos_data(fc)) {
+ u8 *qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
+ tid = qc[0] & 0xf;
+ } else
return;

tl = &lq_data->load[tid];
@@ -1670,7 +1676,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
u16 high_low;
#ifdef CONFIG_IWL4965_HT
u8 tid = MAX_TID_COUNT;
- __le16 *qc;
#endif

IWL_DEBUG_RATE("rate scale calculate new rate for skb\n");
@@ -1693,11 +1698,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;

#ifdef CONFIG_IWL4965_HT
- qc = ieee80211_get_qos_ctrl(hdr);
- if (qc) {
- tid = (u8)(le16_to_cpu(*qc) & 0xf);
- rs_tl_add_packet(lq_sta, tid);
- }
+ rs_tl_add_packet(lq_sta, hdr);
#endif
/*
* Select rate-scale / modulation-mode table to work with in
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index ddb950e..7bd99f9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -650,7 +650,6 @@ extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm);
extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,
const u8 *dest, int left);
-extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr);
extern void iwl4965_update_chain_flags(struct iwl_priv *priv);
int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);

diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index a443472..e4c3f84 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -235,6 +235,25 @@ static inline int ieee80211_is_reassoc_response(u16 fc)
((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_RESP);
}

+static inline int ieee80211_is_qos_data(u16 fc)
+{
+ return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+ ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_QOS_DATA);
+}
+/**
+ * ieee80211_get_qos_ctrl - get pointer to the QoS control field
+ *
+ * This function returns the pointer to 802.11 header QoS field (2 bytes)
+ * This function doesn't check whether hdr is a QoS hdr, use with care
+ * @hdr: struct ieee80211_hdr *hdr
+ * @hdr_len: header length
+ */
+
+static inline u8 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr, int hdr_len)
+{
+ return ((u8 *) hdr + hdr_len - QOS_CONTROL_LEN);
+}
+
static inline int iwl_check_bits(unsigned long field, unsigned long mask)
{
return ((field & mask) == mask) ? 1 : 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index c1234ff..b8fb8d8 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -102,16 +102,6 @@ MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL");

-static __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
-{
- u16 fc = le16_to_cpu(hdr->frame_control);
- int hdr_len = ieee80211_get_hdrlen(fc);
-
- if ((fc & 0x00cc) == (IEEE80211_STYPE_QOS_DATA | IEEE80211_FTYPE_DATA))
- return (__le16 *) ((u8 *) hdr + hdr_len - QOS_CONTROL_LEN);
- return NULL;
-}
-
static const struct ieee80211_supported_band *iwl3945_get_band(
struct iwl3945_priv *priv, enum ieee80211_band band)
{
@@ -2441,7 +2431,6 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
struct ieee80211_hdr *hdr,
int is_unicast, u8 std_id)
{
- __le16 *qc;
u16 fc = le16_to_cpu(hdr->frame_control);
__le32 tx_flags = cmd->cmd.tx.tx_flags;

@@ -2462,12 +2451,13 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
if (ieee80211_get_morefrag(hdr))
tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;

- qc = ieee80211_get_qos_ctrl(hdr);
- if (qc) {
- cmd->cmd.tx.tid_tspec = (u8) (le16_to_cpu(*qc) & 0xf);
+ if (ieee80211_is_qos_data(fc)) {
+ u8 *qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
+ cmd->cmd.tx.tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
- } else
+ } else {
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+ }

if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
tx_flags |= TX_CMD_FLG_RTS_MSK;
@@ -2568,13 +2558,15 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
dma_addr_t phys_addr;
dma_addr_t txcmd_phys;
struct iwl3945_cmd *out_cmd = NULL;
- u16 len, idx, len_org;
- u8 id, hdr_len, unicast;
+ u16 len, idx, len_org, hdr_len;
+ u8 id;
+ u8 unicast;
u8 sta_id;
+ u8 tid = 0;
u16 seq_number = 0;
u16 fc;
- __le16 *qc;
u8 wait_write_ptr = 0;
+ u8 *qc = NULL;
unsigned long flags;
int rc;

@@ -2632,9 +2624,9 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,

IWL_DEBUG_RATE("station Id %d\n", sta_id);

- qc = ieee80211_get_qos_ctrl(hdr);
- if (qc) {
- u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
+ if (ieee80211_is_qos_data(fc)) {
+ qc = ieee80211_get_qos_ctrl(hdr, hdr_len);
+ tid = qc[0] & 0xf;
seq_number = priv->stations[sta_id].tid[tid].seq_number &
IEEE80211_SCTL_SEQ;
hdr->seq_ctrl = cpu_to_le16(seq_number) |
@@ -2745,7 +2737,6 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
if (!ieee80211_get_morefrag(hdr)) {
txq->need_update = 1;
if (qc) {
- u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
priv->stations[sta_id].tid[tid].seq_number = seq_number;
}
} else {
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 6d5b58f..e3f872e 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -89,16 +89,6 @@ MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL");

-__le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
-{
- u16 fc = le16_to_cpu(hdr->frame_control);
- int hdr_len = ieee80211_get_hdrlen(fc);
-
- if ((fc & 0x00cc) == (IEEE80211_STYPE_QOS_DATA | IEEE80211_FTYPE_DATA))
- return (__le16 *) ((u8 *) hdr + hdr_len - QOS_CONTROL_LEN);
- return NULL;
-}
-
static const struct ieee80211_supported_band *iwl_get_hw_mode(
struct iwl_priv *priv, enum ieee80211_band band)
{
@@ -1532,7 +1522,6 @@ static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,
int is_unicast, u8 std_id)
{
- __le16 *qc;
u16 fc = le16_to_cpu(hdr->frame_control);
__le32 tx_flags = cmd->cmd.tx.tx_flags;

@@ -1557,12 +1546,13 @@ static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv,
if (ieee80211_get_morefrag(hdr))
tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;

- qc = ieee80211_get_qos_ctrl(hdr);
- if (qc) {
- cmd->cmd.tx.tid_tspec = (u8) (le16_to_cpu(*qc) & 0xf);
+ if (ieee80211_is_qos_data(fc)) {
+ u8 *qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
+ cmd->cmd.tx.tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
- } else
+ } else {
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+ }

if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
tx_flags |= TX_CMD_FLG_RTS_MSK;
@@ -1614,12 +1604,15 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
dma_addr_t scratch_phys;
struct iwl_cmd *out_cmd = NULL;
u16 len, idx, len_org;
- u8 id, hdr_len, unicast;
+ u8 hdr_len;
+ u8 id;
+ u8 unicast;
u8 sta_id;
+ u8 tid = 0;
+ u8 wait_write_ptr = 0;
u16 seq_number = 0;
u16 fc;
- __le16 *qc;
- u8 wait_write_ptr = 0;
+ u8 *qc = NULL;
unsigned long flags;
int rc;

@@ -1678,9 +1671,9 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,

IWL_DEBUG_TX("station Id %d\n", sta_id);

- qc = ieee80211_get_qos_ctrl(hdr);
- if (qc) {
- u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
+ if (ieee80211_is_qos_data(fc)) {
+ qc = ieee80211_get_qos_ctrl(hdr, hdr_len);
+ tid = qc[0] & 0xf;
seq_number = priv->stations[sta_id].tid[tid].seq_number &
IEEE80211_SCTL_SEQ;
hdr->seq_ctrl = cpu_to_le16(seq_number) |
@@ -1795,10 +1788,8 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,

if (!ieee80211_get_morefrag(hdr)) {
txq->need_update = 1;
- if (qc) {
- u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
+ if (qc)
priv->stations[sta_id].tid[tid].seq_number = seq_number;
- }
} else {
wait_write_ptr = 1;
txq->need_update = 0;
@@ -2377,8 +2368,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
u32 status = le32_to_cpu(tx_resp->status);
#ifdef CONFIG_IWL4965_HT
int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
+ u16 fc;
struct ieee80211_hdr *hdr;
- __le16 *qc;
+ u8 *qc = NULL;
#endif

if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
@@ -2391,10 +2383,11 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,

#ifdef CONFIG_IWL4965_HT
hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, index);
- qc = ieee80211_get_qos_ctrl(hdr);
-
- if (qc)
- tid = le16_to_cpu(*qc) & 0xf;
+ fc = le16_to_cpu(hdr->frame_control);
+ if (ieee80211_is_qos_data(fc)) {
+ qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
+ tid = qc[0] & 0xf;
+ }

sta_id = iwl4965_get_ra_sta_id(priv, hdr);
if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
--
1.5.3.6


2008-05-23 02:11:10

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] mac80211: separate Tx and Rx MCS when configuring HT

From: Ron Rindjunsky <[email protected]>

This patch follows the 11n spec in separation between Tx and Rx MCS
capabilities. Up until now, when configuring the HT possible set of Tx
MCS only Rx MCS were considered, assuming they are the same as the Tx MCS.
This patch fixed this by looking at low level driver Tx capabilities.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl4965-base.c | 14 ++--
include/linux/ieee80211.h | 18 ++++-
net/mac80211/main.c | 96 +++++++++++++++++----------
3 files changed, 83 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 1a2d376..c713b27 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -3958,6 +3958,13 @@ static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
}

+static void iwl4965_nic_start(struct iwl_priv *priv)
+{
+ /* Remove all resets to allow NIC to operate */
+ iwl_write32(priv, CSR_RESET, 0);
+}
+
+
/**
* iwl4965_read_ucode - Read uCode images from disk file.
*
@@ -4447,8 +4454,7 @@ static int __iwl4965_up(struct iwl_priv *priv)
}

/* start card; "initialize" will load runtime ucode */
- /* Remove all resets to allow NIC to operate */
- iwl_write32(priv, CSR_RESET, 0);
+ iwl4965_nic_start(priv);

IWL_DEBUG_INFO(DRV_NAME " is coming up\n");

@@ -6842,10 +6848,6 @@ static int __init iwl4965_init(void)

return ret;

-
-#ifdef CONFIG_IWLWIFI_DEBUG
- pci_unregister_driver(&iwl_driver);
-#endif
error_register:
iwl4965_rate_control_unregister();
return ret;
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index a9102bc..3c2ac0c 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -306,8 +306,18 @@ struct ieee80211_ht_addt_info {
#define IEEE80211_HT_CAP_SGI_40 0x0040
#define IEEE80211_HT_CAP_DELAY_BA 0x0400
#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800
+/* 802.11n HT capability AMPDU settings */
#define IEEE80211_HT_CAP_AMPDU_FACTOR 0x03
#define IEEE80211_HT_CAP_AMPDU_DENSITY 0x1C
+/* 802.11n HT capability MSC set */
+#define IEEE80211_SUPP_MCS_SET_UEQM 4
+#define IEEE80211_HT_CAP_MAX_STREAMS 4
+#define IEEE80211_SUPP_MCS_SET_LEN 10
+/* maximum streams the spec allows */
+#define IEEE80211_HT_CAP_MCS_TX_DEFINED 0x01
+#define IEEE80211_HT_CAP_MCS_TX_RX_DIFF 0x02
+#define IEEE80211_HT_CAP_MCS_TX_STREAMS 0x0C
+#define IEEE80211_HT_CAP_MCS_TX_UEQM 0x10
/* 802.11n HT IE masks */
#define IEEE80211_HT_IE_CHA_SEC_OFFSET 0x03
#define IEEE80211_HT_IE_CHA_WIDTH 0x04
@@ -316,10 +326,10 @@ struct ieee80211_ht_addt_info {
#define IEEE80211_HT_IE_NON_HT_STA_PRSNT 0x0010

/* MIMO Power Save Modes */
-#define WLAN_HT_CAP_MIMO_PS_STATIC 0
-#define WLAN_HT_CAP_MIMO_PS_DYNAMIC 1
-#define WLAN_HT_CAP_MIMO_PS_INVALID 2
-#define WLAN_HT_CAP_MIMO_PS_DISABLED 3
+#define WLAN_HT_CAP_MIMO_PS_STATIC 0
+#define WLAN_HT_CAP_MIMO_PS_DYNAMIC 1
+#define WLAN_HT_CAP_MIMO_PS_INVALID 2
+#define WLAN_HT_CAP_MIMO_PS_DISABLED 3

/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 3601636..b0fddb7 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -35,8 +35,6 @@
#include "debugfs.h"
#include "debugfs_netdev.h"

-#define SUPP_MCS_SET_LEN 16
-
/*
* For seeing transmitted packets on monitor interfaces
* we have a radiotap header too.
@@ -1068,56 +1066,84 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
struct ieee80211_supported_band *sband;
struct ieee80211_ht_info ht_conf;
struct ieee80211_ht_bss_info ht_bss_conf;
- int i;
u32 changed = 0;
+ int i;
+ u8 max_tx_streams = IEEE80211_HT_CAP_MAX_STREAMS;
+ u8 tx_mcs_set_cap;

sband = local->hw.wiphy->bands[conf->channel->band];

+ memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info));
+ memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info));
+
/* HT is not supported */
if (!sband->ht_info.ht_supported) {
conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
- return 0;
+ goto out;
}

- memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info));
- memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info));
-
- if (enable_ht) {
- if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE))
+ /* disable HT */
+ if (!enable_ht) {
+ if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)
changed |= BSS_CHANGED_HT;
+ conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
+ conf->ht_conf.ht_supported = 0;
+ goto out;
+ }

- conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
- ht_conf.ht_supported = 1;

- ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap;
- ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS);
- ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS;
+ if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE))
+ changed |= BSS_CHANGED_HT;

- for (i = 0; i < SUPP_MCS_SET_LEN; i++)
- ht_conf.supp_mcs_set[i] =
- sband->ht_info.supp_mcs_set[i] &
- req_ht_cap->supp_mcs_set[i];
+ conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
+ ht_conf.ht_supported = 1;

- ht_bss_conf.primary_channel = req_bss_cap->primary_channel;
- ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
- ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
+ ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap;
+ ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS);
+ ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS;
+ ht_bss_conf.primary_channel = req_bss_cap->primary_channel;
+ ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
+ ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;

- ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
- ht_conf.ampdu_density = req_ht_cap->ampdu_density;
+ ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
+ ht_conf.ampdu_density = req_ht_cap->ampdu_density;

- /* if bss configuration changed store the new one */
- if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) ||
- memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) {
- changed |= BSS_CHANGED_HT;
- memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf));
- memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf));
- }
- } else {
- if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)
- changed |= BSS_CHANGED_HT;
- conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
- }
+ /* Bits 96-100 */
+ tx_mcs_set_cap = sband->ht_info.supp_mcs_set[12];

+ /* configure suppoerted Tx MCS according to requested MCS
+ * (based in most cases on Rx capabilities of peer) and self
+ * Tx MCS capabilities (as defined by low level driver HW
+ * Tx capabilities) */
+ if (!(tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_DEFINED))
+ goto check_changed;
+
+ /* Counting from 0 therfore + 1 */
+ if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_RX_DIFF)
+ max_tx_streams = ((tx_mcs_set_cap &
+ IEEE80211_HT_CAP_MCS_TX_STREAMS) >> 2) + 1;
+
+ for (i = 0; i < max_tx_streams; i++)
+ ht_conf.supp_mcs_set[i] =
+ sband->ht_info.supp_mcs_set[i] &
+ req_ht_cap->supp_mcs_set[i];
+
+ if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_UEQM)
+ for (i = IEEE80211_SUPP_MCS_SET_UEQM;
+ i < IEEE80211_SUPP_MCS_SET_LEN; i++)
+ ht_conf.supp_mcs_set[i] =
+ sband->ht_info.supp_mcs_set[i] &
+ req_ht_cap->supp_mcs_set[i];
+
+check_changed:
+ /* if bss configuration changed store the new one */
+ if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) ||
+ memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) {
+ changed |= BSS_CHANGED_HT;
+ memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf));
+ memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf));
+ }
+out:
return changed;
}

--
1.5.3.6


2008-05-23 02:11:09

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: filling Tx MCS set

From: Ron Rindjunsky <[email protected]>

This patch fills the needed data about HW capabilities in matters of
possible HT Tx MCS.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-core.c | 33 +++++++++++++++++++++++++-----
1 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index d3cbad2..a2f4f28 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -317,24 +317,33 @@ void iwl_reset_qos(struct iwl_priv *priv)
EXPORT_SYMBOL(iwl_reset_qos);

#ifdef CONFIG_IWL4965_HT
+#define MAX_BIT_RATE_40_MHZ 0x96; /* 150 Mbps */
+#define MAX_BIT_RATE_20_MHZ 0x48; /* 72 Mbps */
static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
struct ieee80211_ht_info *ht_info,
enum ieee80211_band band)
{
+ u16 max_bit_rate = 0;
+ u8 rx_chains_num = priv->hw_params.rx_chains_num;
+ u8 tx_chains_num = priv->hw_params.tx_chains_num;
+
ht_info->cap = 0;
memset(ht_info->supp_mcs_set, 0, 16);

ht_info->ht_supported = 1;

+ ht_info->cap |= (u16)IEEE80211_HT_CAP_GRN_FLD;
+ ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20;
+ ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS &
+ (IWL_MIMO_PS_NONE << 2));
+
+ max_bit_rate = MAX_BIT_RATE_20_MHZ;
if (priv->hw_params.fat_channel & BIT(band)) {
ht_info->cap |= (u16)IEEE80211_HT_CAP_SUP_WIDTH;
ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_40;
ht_info->supp_mcs_set[4] = 0x01;
+ max_bit_rate = MAX_BIT_RATE_40_MHZ;
}
- ht_info->cap |= (u16)IEEE80211_HT_CAP_GRN_FLD;
- ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20;
- ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS &
- (IWL_MIMO_PS_NONE << 2));

if (priv->cfg->mod_params->amsdu_size_8K)
ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU;
@@ -343,10 +352,22 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;

ht_info->supp_mcs_set[0] = 0xFF;
- if (priv->hw_params.tx_chains_num >= 2)
+ if (rx_chains_num >= 2)
ht_info->supp_mcs_set[1] = 0xFF;
- if (priv->hw_params.tx_chains_num >= 3)
+ if (rx_chains_num >= 3)
ht_info->supp_mcs_set[2] = 0xFF;
+
+ /* Highest supported Rx data rate */
+ max_bit_rate *= rx_chains_num;
+ ht_info->supp_mcs_set[10] = (u8)(max_bit_rate & 0x00FF);
+ ht_info->supp_mcs_set[11] = (u8)((max_bit_rate & 0xFF00) >> 8);
+
+ /* Tx MCS capabilities */
+ ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED;
+ if (tx_chains_num != rx_chains_num) {
+ ht_info->supp_mcs_set[12] |= IEEE80211_HT_CAP_MCS_TX_RX_DIFF;
+ ht_info->supp_mcs_set[12] |= ((tx_chains_num - 1) << 2);
+ }
}
#else
static inline void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
--
1.5.3.6


2008-05-23 14:29:36

by John W. Linville

[permalink] [raw]
Subject: Re: [PATCH 00/51] iwlwifi driver 05/23 updates

On Fri, May 23, 2008 at 03:26:27PM +0200, Holger Schurig wrote:
> > It should be fine as-is, especially since you sent each as a
> > reply to the previous.
>
> However, sending LOTS of patches via this way looks funny in
> several e-mail clients. Here's an example with KMail:

That is true. OTOH, sending them as individual messages (or as replies
to a single "0/N" message) can cause them to arrive out of order.

In most cases patches sent as a group need to be applied in a certain
order. In many cases they will fail to apply, and in others they
might apply out of order but not be "bisectable" out of order.

IMHO it is a lot easier to deal with the "funny looking" mailbox
window than to deal with the issues caused by misordered patches.

John
--
John W. Linville
[email protected]

2008-05-23 02:11:16

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: remove 4956 form iwl4965_tx_cmd

From: Tomas Winkler <[email protected]>

This patch renames iwl4965_tx_cmd to iwl_tx_cmd and cleans
collateral code.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 3 +--
drivers/net/wireless/iwlwifi/iwl-5000.c | 1 -
drivers/net/wireless/iwlwifi/iwl-commands.h | 6 +++---
drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +---
drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 ++--
5 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index aeaf5f7..02bbe04 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1053,7 +1053,6 @@ int iwl4965_hw_set_hw_params(struct iwl_priv *priv)

priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto;
- priv->hw_params.tx_cmd_len = sizeof(struct iwl4965_tx_cmd);
priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
if (priv->cfg->mod_params->amsdu_size_8K)
@@ -1943,7 +1942,7 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
struct ieee80211_hdr *hdr, int sta_id,
int is_hcca)
{
- struct iwl4965_tx_cmd *tx = &cmd->cmd.tx;
+ struct iwl_tx_cmd *tx = &cmd->cmd.tx;
u8 rts_retry_limit = 0;
u8 data_retry_limit = 0;
u16 fc = le16_to_cpu(hdr->frame_control);
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 72d655c..d155247 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -298,7 +298,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)

priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto;
- priv->hw_params.tx_cmd_len = sizeof(struct iwl4965_tx_cmd);
priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
if (priv->cfg->mod_params->amsdu_size_8K)
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 350af1b..dd84326 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -1196,7 +1196,7 @@ struct iwl4965_dram_scratch {
/*
* REPLY_TX = 0x1c (command)
*/
-struct iwl4965_tx_cmd {
+struct iwl_tx_cmd {
/*
* MPDU byte count:
* MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
@@ -2135,7 +2135,7 @@ struct iwl4965_scan_cmd {

/* For active scans (set to all-0s for passive scans).
* Does not include payload. Must specify Tx rate; no rate scaling. */
- struct iwl4965_tx_cmd tx_cmd;
+ struct iwl_tx_cmd tx_cmd;

/* For directed active scans (set to all-0s otherwise) */
struct iwl4965_ssid_ie direct_scan[PROBE_OPTION_MAX];
@@ -2232,7 +2232,7 @@ struct iwl4965_beacon_notif {
* REPLY_TX_BEACON = 0x91 (command, has simple generic response)
*/
struct iwl4965_tx_beacon_cmd {
- struct iwl4965_tx_cmd tx;
+ struct iwl_tx_cmd tx;
__le16 tim_idx;
u8 tim_size;
u8 reserved1;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 565d7dc..ddb950e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -329,7 +329,7 @@ struct iwl_cmd {
struct iwl4965_rxon_time_cmd rxon_time;
struct iwl4965_powertable_cmd powertable;
struct iwl4965_qosparam_cmd qosparam;
- struct iwl4965_tx_cmd tx;
+ struct iwl_tx_cmd tx;
struct iwl4965_tx_beacon_cmd tx_beacon;
struct iwl4965_rxon_assoc_cmd rxon_assoc;
u8 *indirect;
@@ -573,7 +573,6 @@ struct iwl_sensitivity_ranges {
/**
* struct iwl_hw_params
* @max_txq_num: Max # Tx queues supported
- * @tx_cmd_len: Size of Tx command (but not including frame itself)
* @tx/rx_chains_num: Number of TX/RX chains
* @valid_tx/rx_ant: usable antennas
* @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
@@ -590,7 +589,6 @@ struct iwl_sensitivity_ranges {
*/
struct iwl_hw_params {
u16 max_txq_num;
- u16 tx_cmd_len;
u8 tx_chains_num;
u8 rx_chains_num;
u8 valid_tx_ant;
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 88032cc..6d5b58f 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1740,7 +1740,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
* of the MAC header (device reads on dword boundaries).
* We'll tell device about this padding later.
*/
- len = priv->hw_params.tx_cmd_len +
+ len = sizeof(struct iwl_tx_cmd) +
sizeof(struct iwl_cmd_header) + hdr_len;

len_org = len;
@@ -1789,7 +1789,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
iwl_update_tx_stats(priv, fc, len);

scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
- offsetof(struct iwl4965_tx_cmd, scratch);
+ offsetof(struct iwl_tx_cmd, scratch);
out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys);
out_cmd->cmd.tx.dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys);

--
1.5.3.6


2008-05-23 02:11:52

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: setup correctly L1 L0S pi link values

From: Tomas Winkler <[email protected]>

This patch setups L1 L0S pci link values.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 7 ++++++-
drivers/net/wireless/iwlwifi/iwl-4965.c | 18 ++++++++++++++----
drivers/net/wireless/iwlwifi/iwl-5000.c | 19 ++++++++++++++-----
drivers/net/wireless/iwlwifi/iwl-csr.h | 6 +++++-
4 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index ee55b28..fc11833 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -100,9 +100,14 @@

#include "iwl-commands.h"

-#define PCI_LINK_CTRL 0x0F0
+/* PCI registers */
+#define PCI_LINK_CTRL 0x0F0 /* 1 byte */
#define PCI_POWER_SOURCE 0x0C8
#define PCI_REG_WUM8 0x0E8
+
+/* PCI register values */
+#define PCI_LINK_VAL_L0S_EN 0x01
+#define PCI_LINK_VAL_L1_EN 0x02
#define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000)

#define TFD_QUEUE_SIZE_MAX (256)
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 547287c..02d3dc0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -500,6 +500,10 @@ static int iwl4965_apm_init(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);

+ /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */
+ iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
+
/* set "initialization complete" bit to move adapter
* D0U* --> D0A* state */
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
@@ -518,11 +522,12 @@ static int iwl4965_apm_init(struct iwl_priv *priv)
goto out;

/* enable DMA */
- iwl_write_prph(priv, APMG_CLK_CTRL_REG,
- APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
+ iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT |
+ APMG_CLK_VAL_BSM_CLK_RQT);

udelay(20);

+ /* disable L1-Active */
iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);

@@ -550,8 +555,13 @@ static void iwl4965_nic_config(struct iwl_priv *priv)

pci_read_config_byte(priv->pci_dev, PCI_LINK_CTRL, &val_link);

- /* disable L1 entry -- workaround for pre-B1 */
- pci_write_config_byte(priv->pci_dev, PCI_LINK_CTRL, val_link & ~0x02);
+ /* L1 is enabled by BIOS */
+ if ((val_link & PCI_LINK_VAL_L1_EN) == PCI_LINK_VAL_L1_EN)
+ /* diable L0S disabled L1A enabled */
+ iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
+ else
+ /* L0S enabled L1A disabled */
+ iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);

radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 0355ccd..b1c5045 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -63,6 +63,10 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);

+ /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */
+ iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
+
iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);

/* set "initialization complete" bit to move adapter
@@ -83,13 +87,13 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
return ret;

/* enable DMA */
- iwl_write_prph(priv, APMG_CLK_EN_REG,
- APMG_CLK_VAL_DMA_CLK_RQT);
+ iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);

udelay(20);

+ /* disable L1-Active */
iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
- APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+ APMG_PCIDEV_STT_VAL_L1_ACT_DIS);

iwl_release_nic_access(priv);

@@ -106,8 +110,13 @@ static void iwl5000_nic_config(struct iwl_priv *priv)

pci_read_config_byte(priv->pci_dev, PCI_LINK_CTRL, &val_link);

- /* disable L1 entry -- workaround for pre-B1 */
- pci_write_config_byte(priv->pci_dev, PCI_LINK_CTRL, val_link & ~0x02);
+ /* L1 is enabled by BIOS */
+ if ((val_link & PCI_LINK_VAL_L1_EN) == PCI_LINK_VAL_L1_EN)
+ /* diable L0S disabled L1A enabled */
+ iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
+ else
+ /* L0S enabled L1A disabled */
+ iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);

radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);

diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 9d6e5d2..545ed69 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -87,13 +87,14 @@
/* EEPROM reads */
#define CSR_EEPROM_REG (CSR_BASE+0x02c)
#define CSR_EEPROM_GP (CSR_BASE+0x030)
+#define CSR_GIO_REG (CSR_BASE+0x03C)
#define CSR_GP_UCODE (CSR_BASE+0x044)
#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
-#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
#define CSR_LED_REG (CSR_BASE+0x094)
+#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)

/* Analog phase-lock-loop configuration */
#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
@@ -213,6 +214,9 @@
#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)

+/* CSR GIO */
+#define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002)
+
/* UCODE DRV GP */
#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
--
1.5.3.6


2008-05-23 02:11:11

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: remove 4965 from iwl4965_tx_queue_update_write_ptr

From: Tomas Winkler <[email protected]>

This patch renames iwl4965_tx_queue_update_write_ptr to
iwl_txq_update_write_ptr. This is a preparation for moving to iwl-tx.c.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl4965-base.c | 38 +++++++++++++-------------
1 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 45b6b52..0ad9558 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -53,7 +53,7 @@
#include "iwl-sta.h"
#include "iwl-calib.h"

-static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
+static int iwl_txq_update_write_ptr(struct iwl_priv *priv,
struct iwl_tx_queue *txq);

/******************************************************************************
@@ -417,7 +417,7 @@ int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)

/* Increment and update queue's write index */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- ret = iwl4965_tx_queue_update_write_ptr(priv, txq);
+ ret = iwl_txq_update_write_ptr(priv, txq);

spin_unlock_irqrestore(&priv->hcmd_lock, flags);
return ret ? ret : idx;
@@ -1978,7 +1978,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,

/* Tell device the write index *just past* this latest filled TFD */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- rc = iwl4965_tx_queue_update_write_ptr(priv, txq);
+ rc = iwl_txq_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags);

if (rc)
@@ -1989,7 +1989,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
if (wait_write_ptr) {
spin_lock_irqsave(&priv->lock, flags);
txq->need_update = 1;
- iwl4965_tx_queue_update_write_ptr(priv, txq);
+ iwl_txq_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags);
}

@@ -3272,17 +3272,17 @@ int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
}

/**
- * iwl4965_tx_queue_update_write_ptr - Send new write index to hardware
+ * iwl_txq_update_write_ptr - Send new write index to hardware
*/
-static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
+static int iwl_txq_update_write_ptr(struct iwl_priv *priv,
struct iwl_tx_queue *txq)
{
u32 reg = 0;
- int rc = 0;
+ int ret = 0;
int txq_id = txq->q.id;

if (txq->need_update == 0)
- return rc;
+ return ret;

/* if we're trying to save power */
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
@@ -3295,13 +3295,13 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
iwl_set_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- return rc;
+ return ret;
}

/* restore this queue's parameters in nic hardware. */
- rc = iwl_grab_nic_access(priv);
- if (rc)
- return rc;
+ ret = iwl_grab_nic_access(priv);
+ if (ret)
+ return ret;
iwl_write_direct32(priv, HBUS_TARG_WRPTR,
txq->q.write_ptr | (txq_id << 8));
iwl_release_nic_access(priv);
@@ -3314,7 +3314,7 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,

txq->need_update = 0;

- return rc;
+ return ret;
}

#ifdef CONFIG_IWLWIFI_DEBUG
@@ -3706,12 +3706,12 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
if (inta & CSR_INT_BIT_WAKEUP) {
IWL_DEBUG_ISR("Wakeup interrupt\n");
iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
- iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[0]);
- iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[1]);
- iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[2]);
- iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[3]);
- iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[4]);
- iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[5]);
+ iwl_txq_update_write_ptr(priv, &priv->txq[0]);
+ iwl_txq_update_write_ptr(priv, &priv->txq[1]);
+ iwl_txq_update_write_ptr(priv, &priv->txq[2]);
+ iwl_txq_update_write_ptr(priv, &priv->txq[3]);
+ iwl_txq_update_write_ptr(priv, &priv->txq[4]);
+ iwl_txq_update_write_ptr(priv, &priv->txq[5]);

handled |= CSR_INT_BIT_WAKEUP;
}
--
1.5.3.6


2008-05-23 02:12:11

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: impelemnt 5000 tx response path

From: Ron Rindjunsky <[email protected]>

This patch implements 5000 HW tx response path

Signed-off-by: Ron Rindjunsky <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-5000.c | 235 +++++++++++++++++++++++++++++++
net/mac80211/mlme.c | 10 +-
2 files changed, 240 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 685a84e..5d6a28c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -972,6 +972,240 @@ static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
iwl_write_prph(priv, IWL50_SCD_TXFACT, mask);
}

+
+static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp)
+{
+ __le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status +
+ tx_resp->frame_count);
+ return le32_to_cpu(*scd_ssn) & MAX_SN;
+
+}
+
+static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
+ struct iwl_ht_agg *agg,
+ struct iwl5000_tx_resp *tx_resp,
+ u16 start_idx)
+{
+ u16 status;
+ struct agg_tx_status *frame_status = &tx_resp->status;
+ struct ieee80211_tx_status *tx_status = NULL;
+ struct ieee80211_hdr *hdr = NULL;
+ int i, sh;
+ int txq_id, idx;
+ u16 seq;
+
+ if (agg->wait_for_ba)
+ IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n");
+
+ agg->frame_count = tx_resp->frame_count;
+ agg->start_idx = start_idx;
+ agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+ agg->bitmap = 0;
+
+ /* # frames attempted by Tx command */
+ if (agg->frame_count == 1) {
+ /* Only one frame was attempted; no block-ack will arrive */
+ status = le16_to_cpu(frame_status[0].status);
+ seq = le16_to_cpu(frame_status[0].sequence);
+ idx = SEQ_TO_INDEX(seq);
+ txq_id = SEQ_TO_QUEUE(seq);
+
+ /* FIXME: code repetition */
+ IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
+ agg->frame_count, agg->start_idx, idx);
+
+ tx_status = &(priv->txq[txq_id].txb[idx].status);
+ tx_status->retry_count = tx_resp->failure_frame;
+ tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU;
+ tx_status->flags = iwl_is_tx_success(status)?
+ IEEE80211_TX_STATUS_ACK : 0;
+ iwl4965_hwrate_to_tx_control(priv,
+ le32_to_cpu(tx_resp->rate_n_flags),
+ &tx_status->control);
+ /* FIXME: code repetition end */
+
+ IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
+ status & 0xff, tx_resp->failure_frame);
+ IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n",
+ iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags));
+
+ agg->wait_for_ba = 0;
+ } else {
+ /* Two or more frames were attempted; expect block-ack */
+ u64 bitmap = 0;
+ int start = agg->start_idx;
+
+ /* Construct bit-map of pending frames within Tx window */
+ for (i = 0; i < agg->frame_count; i++) {
+ u16 sc;
+ status = le16_to_cpu(frame_status[i].status);
+ seq = le16_to_cpu(frame_status[i].sequence);
+ idx = SEQ_TO_INDEX(seq);
+ txq_id = SEQ_TO_QUEUE(seq);
+
+ if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
+ AGG_TX_STATE_ABORT_MSK))
+ continue;
+
+ IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n",
+ agg->frame_count, txq_id, idx);
+
+ hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
+
+ sc = le16_to_cpu(hdr->seq_ctrl);
+ if (idx != (SEQ_TO_SN(sc) & 0xff)) {
+ IWL_ERROR("BUG_ON idx doesn't match seq control"
+ " idx=%d, seq_idx=%d, seq=%d\n",
+ idx, SEQ_TO_SN(sc),
+ hdr->seq_ctrl);
+ return -1;
+ }
+
+ IWL_DEBUG_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n",
+ i, idx, SEQ_TO_SN(sc));
+
+ sh = idx - start;
+ if (sh > 64) {
+ sh = (start - idx) + 0xff;
+ bitmap = bitmap << sh;
+ sh = 0;
+ start = idx;
+ } else if (sh < -64)
+ sh = 0xff - (start - idx);
+ else if (sh < 0) {
+ sh = start - idx;
+ start = idx;
+ bitmap = bitmap << sh;
+ sh = 0;
+ }
+ bitmap |= (1 << sh);
+ IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n",
+ start, (u32)(bitmap & 0xFFFFFFFF));
+ }
+
+ agg->bitmap = bitmap;
+ agg->start_idx = start;
+ agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+ IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n",
+ agg->frame_count, agg->start_idx,
+ (unsigned long long)agg->bitmap);
+
+ if (bitmap)
+ agg->wait_for_ba = 1;
+ }
+ return 0;
+}
+
+static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+ int txq_id = SEQ_TO_QUEUE(sequence);
+ int index = SEQ_TO_INDEX(sequence);
+ struct iwl_tx_queue *txq = &priv->txq[txq_id];
+ struct ieee80211_tx_status *tx_status;
+ struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+ u32 status = le16_to_cpu(tx_resp->status.status);
+#ifdef CONFIG_IWL4965_HT
+ int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
+ u16 fc;
+ struct ieee80211_hdr *hdr;
+ u8 *qc = NULL;
+#endif
+
+ if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
+ IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
+ "is out of range [0-%d] %d %d\n", txq_id,
+ index, txq->q.n_bd, txq->q.write_ptr,
+ txq->q.read_ptr);
+ return;
+ }
+
+#ifdef CONFIG_IWL4965_HT
+ hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
+ fc = le16_to_cpu(hdr->frame_control);
+ if (ieee80211_is_qos_data(fc)) {
+ qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
+ tid = qc[0] & 0xf;
+ }
+
+ sta_id = iwl_get_ra_sta_id(priv, hdr);
+ if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
+ IWL_ERROR("Station not known\n");
+ return;
+ }
+
+ if (txq->sched_retry) {
+ const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp);
+ struct iwl_ht_agg *agg = NULL;
+
+ if (!qc)
+ return;
+
+ agg = &priv->stations[sta_id].tid[tid].agg;
+
+ iwl5000_tx_status_reply_tx(priv, agg, tx_resp, index);
+
+ if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) {
+ /* TODO: send BAR */
+ }
+
+ if (txq->q.read_ptr != (scd_ssn & 0xff)) {
+ int freed, ampdu_q;
+ index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
+ IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
+ "%d index %d\n", scd_ssn , index);
+ freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
+ priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+
+ if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
+ txq_id >= 0 && priv->mac80211_registered &&
+ agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
+ /* calculate mac80211 ampdu sw queue to wake */
+ ampdu_q = txq_id - IWL_BACK_QUEUE_FIRST_ID +
+ priv->hw->queues;
+ if (agg->state == IWL_AGG_OFF)
+ ieee80211_wake_queue(priv->hw, txq_id);
+ else
+ ieee80211_wake_queue(priv->hw, ampdu_q);
+ }
+ iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
+ }
+ } else {
+#endif /* CONFIG_IWL4965_HT */
+ tx_status = &(txq->txb[txq->q.read_ptr].status);
+
+ tx_status->retry_count = tx_resp->failure_frame;
+ tx_status->flags =
+ iwl_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
+ iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
+ &tx_status->control);
+
+ IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
+ "retries %d\n", txq_id, iwl_get_tx_fail_reason(status),
+ status, le32_to_cpu(tx_resp->rate_n_flags),
+ tx_resp->failure_frame);
+
+ IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
+#ifdef CONFIG_IWL4965_HT
+ if (index != -1) {
+ int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
+ if (tid != MAX_TID_COUNT)
+ priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+ if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
+ (txq_id >= 0) && priv->mac80211_registered)
+ ieee80211_wake_queue(priv->hw, txq_id);
+ if (tid != MAX_TID_COUNT)
+ iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
+ }
+ }
+#endif /* CONFIG_IWL4965_HT */
+
+ if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
+ IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
+}
+
/* Currently 5000 is the supperset of everything */
static u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len)
{
@@ -985,6 +1219,7 @@ static void iwl5000_rx_handler_setup(struct iwl_priv *priv)
iwl5000_rx_calib_result;
priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
iwl5000_rx_calib_complete;
+ priv->rx_handlers[REPLY_TX] = iwl5000_rx_reply_tx;
}


diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 3f7f92a..fd42ffd 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -4083,17 +4083,17 @@ ieee80211_sta_scan_result(struct net_device *dev,
IW_EV_UINT_LEN);
}

+
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = bss->freq;
- iwe.u.freq.e = 6;
+ iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq);
+ iwe.u.freq.e = 0;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_FREQ_LEN);
-
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq);
- iwe.u.freq.e = 0;
+ iwe.u.freq.m = bss->freq;
+ iwe.u.freq.e = 6;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_FREQ_LEN);

--
1.5.3.6


2008-05-23 02:11:08

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: remove iwl4965_nic_start function

From: Ron Rindjunsky <[email protected]>

This patch moves the contant of iwl4965_nic_start to the only place it is
being used.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl4965-base.c | 10 ++--------
1 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index d0f948d..1a2d376 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -3958,13 +3958,6 @@ static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
}

-static void iwl4965_nic_start(struct iwl_priv *priv)
-{
- /* Remove all resets to allow NIC to operate */
- iwl_write32(priv, CSR_RESET, 0);
-}
-
-
/**
* iwl4965_read_ucode - Read uCode images from disk file.
*
@@ -4454,7 +4447,8 @@ static int __iwl4965_up(struct iwl_priv *priv)
}

/* start card; "initialize" will load runtime ucode */
- iwl4965_nic_start(priv);
+ /* Remove all resets to allow NIC to operate */
+ iwl_write32(priv, CSR_RESET, 0);

IWL_DEBUG_INFO(DRV_NAME " is coming up\n");

--
1.5.3.6


2008-05-23 12:58:07

by John W. Linville

[permalink] [raw]
Subject: Re: [PATCH 00/51] iwlwifi driver 05/23 updates

On Fri, May 23, 2008 at 10:45:42AM +0800, Zhu Yi wrote:
> On Fri, 2008-05-23 at 10:08 +0800, Zhu Yi wrote:
> > Here are some iwlwifi drivers update. Please apply.
>
> I forgot to put a series number for each patch. If you think that
> matters, I'll resubmit.

It should be fine as-is, especially since you sent each as a reply
to the previous.

Thanks,

John
--
John W. Linville
[email protected]

2008-05-23 02:12:01

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: move add sta handler to iwl-sta.c

From: Tomas Winkler <[email protected]>

This patch moves add_sta hander to iwl-sta.c.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-sta.c | 37 ++++++++++++++++++++++++++-
drivers/net/wireless/iwlwifi/iwl4965-base.c | 10 -------
2 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 11ec408..ed07566 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -74,6 +74,39 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
}
EXPORT_SYMBOL(iwl_find_station);

+static int iwl_add_sta_callback(struct iwl_priv *priv,
+ struct iwl_cmd *cmd, struct sk_buff *skb)
+{
+ struct iwl_rx_packet *res = NULL;
+
+ if (!skb) {
+ IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
+ return 1;
+ }
+
+ res = (struct iwl_rx_packet *)skb->data;
+ if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
+ IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
+ res->hdr.flags);
+ return 1;
+ }
+
+ switch (res->u.add_sta.status) {
+ case ADD_STA_SUCCESS_MSK:
+ /* FIXME: implement iwl_sta_ucode_activate(priv, addr); */
+ /* fail through */
+ default:
+ IWL_DEBUG_HC("Received REPLY_ADD_STA:(0x%08X)\n",
+ 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,
struct iwl_addsta_cmd *sta, u8 flags)
{
@@ -86,7 +119,9 @@ int iwl_send_add_sta(struct iwl_priv *priv,
.data = data,
};

- if (!(flags & CMD_ASYNC))
+ if (flags & CMD_ASYNC)
+ cmd.meta.u.callback = iwl_add_sta_callback;
+ else
cmd.meta.flags |= CMD_WANT_SKB;

cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index ea622db..7fe1bb9 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1929,15 +1929,6 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv,
IWL_WARNING("uCode did not respond OK.\n");
}

-static void iwl4965_rx_reply_add_sta(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-
- IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
- return;
-}
-
static void iwl4965_rx_reply_error(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
@@ -2246,7 +2237,6 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
{
priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
- priv->rx_handlers[REPLY_ADD_STA] = iwl4965_rx_reply_add_sta;
priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error;
priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl4965_rx_csa;
priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
--
1.5.3.6


2008-05-23 02:12:05

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi-5000: implement initial calibration for 5000

From: Tomas Winkler <[email protected]>

This patch adds initial calibration framework for 5000 HW faimily.

Signed-off-by: Tomas Winkler <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
Signed-off-by: Ron Rindjunsky <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-5000.c | 127 +++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-commands.h | 50 +++++++++++
drivers/net/wireless/iwlwifi/iwl-core.c | 16 ++++
drivers/net/wireless/iwlwifi/iwl-core.h | 1 +
drivers/net/wireless/iwlwifi/iwl-dev.h | 12 +++
drivers/net/wireless/iwlwifi/iwl-eeprom.h | 1 +
drivers/net/wireless/iwlwifi/iwl-hcmd.c | 4 +
7 files changed, 211 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index a94cd36..eb6141e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -395,6 +395,8 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {

#endif /* CONFIG_IWL5000_RUN_TIME_CALIB */

+
+
static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
size_t offset)
{
@@ -404,6 +406,118 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
}

/*
+ * Calibration
+ */
+static int iwl5000_send_Xtal_calib(struct iwl_priv *priv)
+{
+ u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL);
+
+ struct iwl5000_calibration cal_cmd = {
+ .op_code = IWL5000_PHY_CALIBRATE_CRYSTAL_FRQ_CMD,
+ .data = {
+ (u8)xtal_calib[0],
+ (u8)xtal_calib[1],
+ }
+ };
+
+ return iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+ sizeof(cal_cmd), &cal_cmd);
+}
+
+static int iwl5000_send_calib_results(struct iwl_priv *priv)
+{
+ int ret = 0;
+
+ if (priv->calib_results.lo_res)
+ ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+ priv->calib_results.lo_res_len,
+ priv->calib_results.lo_res);
+ if (ret)
+ goto err;
+
+
+ if (priv->calib_results.tx_iq_res)
+ ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+ priv->calib_results.tx_iq_res_len,
+ priv->calib_results.tx_iq_res);
+
+ if (ret)
+ goto err;
+
+ if (priv->calib_results.tx_iq_perd_res)
+ ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+ priv->calib_results.tx_iq_perd_res_len,
+ priv->calib_results.tx_iq_perd_res);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ IWL_ERROR("Error %d\n", ret);
+ return ret;
+}
+
+static int iwl5000_send_calib_cfg(struct iwl_priv *priv)
+{
+ struct iwl5000_calib_cfg_cmd calib_cfg_cmd;
+ struct iwl_host_cmd cmd = {
+ .id = CALIBRATION_CFG_CMD,
+ .len = sizeof(struct iwl5000_calib_cfg_cmd),
+ .data = &calib_cfg_cmd,
+ };
+
+ memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
+ calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
+ calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL;
+ calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL;
+ calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL;
+
+ return iwl_send_cmd(priv, &cmd);
+}
+
+static void iwl5000_rx_calib_result(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl5000_calib_hdr *hdr = (struct iwl5000_calib_hdr *)pkt->u.raw;
+ int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK;
+
+ iwl_free_calib_results(priv);
+
+ /* reduce the size of the length field itself */
+ len -= 4;
+
+ switch (hdr->op_code) {
+ case IWL5000_PHY_CALIBRATE_LO_CMD:
+ priv->calib_results.lo_res = kzalloc(len, GFP_ATOMIC);
+ priv->calib_results.lo_res_len = len;
+ memcpy(priv->calib_results.lo_res, pkt->u.raw, len);
+ break;
+ case IWL5000_PHY_CALIBRATE_TX_IQ_CMD:
+ priv->calib_results.tx_iq_res = kzalloc(len, GFP_ATOMIC);
+ priv->calib_results.tx_iq_res_len = len;
+ memcpy(priv->calib_results.tx_iq_res, pkt->u.raw, len);
+ break;
+ case IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD:
+ priv->calib_results.tx_iq_perd_res = kzalloc(len, GFP_ATOMIC);
+ priv->calib_results.tx_iq_perd_res_len = len;
+ memcpy(priv->calib_results.tx_iq_perd_res, pkt->u.raw, len);
+ break;
+ default:
+ IWL_ERROR("Unknown calibration notification %d\n",
+ hdr->op_code);
+ return;
+ }
+}
+
+static void iwl5000_rx_calib_complete(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ IWL_DEBUG_INFO("Init. calibration is completed, restarting fw.\n");
+ queue_work(priv->workqueue, &priv->restart);
+}
+
+/*
* ucode
*/
static int iwl5000_load_section(struct iwl_priv *priv,
@@ -565,6 +679,7 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv)
goto restart;
}

+ iwl5000_send_calib_cfg(priv);
return;

restart:
@@ -684,8 +799,14 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);

+
iwl5000_send_wimax_coex(priv);

+ iwl5000_send_Xtal_calib(priv);
+
+ if (priv->ucode_type == UCODE_RT)
+ iwl5000_send_calib_results(priv);
+
return 0;
}

@@ -856,8 +977,14 @@ static u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len)

static void iwl5000_rx_handler_setup(struct iwl_priv *priv)
{
+ /* init calibration handlers */
+ priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
+ iwl5000_rx_calib_result;
+ priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
+ iwl5000_rx_calib_complete;
}

+
static int iwl5000_hw_valid_rtc_data_addr(u32 addr)
{
return (addr >= RTC_DATA_LOWER_BOUND) &&
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index a637abe..6f62beb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -2778,10 +2778,59 @@ enum {
IWL5000_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
IWL5000_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
IWL5000_PHY_CALIBRATE_BASE_BAND_CMD = 16,
+ IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD = 18,
IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD = 19,
};

+enum {
+ CALIBRATION_CFG_CMD = 0x65,
+ CALIBRATION_RES_NOTIFICATION = 0x66,
+ CALIBRATION_COMPLETE_NOTIFICATION = 0x67
+};
+
+struct iwl_cal_crystal_freq_cmd {
+ u8 cap_pin1;
+ u8 cap_pin2;
+} __attribute__ ((packed));
+
+struct iwl5000_calibration {
+ u8 op_code;
+ u8 first_group;
+ u8 num_groups;
+ u8 all_data_valid;
+ struct iwl_cal_crystal_freq_cmd data;
+} __attribute__ ((packed));
+
+#define IWL_CALIB_INIT_CFG_ALL __constant_cpu_to_le32(0xffffffff)
+
+struct iwl_calib_cfg_elmnt_s {
+ __le32 is_enable;
+ __le32 start;
+ __le32 send_res;
+ __le32 apply_res;
+ __le32 reserved;
+} __attribute__ ((packed));
+
+struct iwl_calib_cfg_status_s {
+ struct iwl_calib_cfg_elmnt_s once;
+ struct iwl_calib_cfg_elmnt_s perd;
+ __le32 flags;
+} __attribute__ ((packed));
+
+struct iwl5000_calib_cfg_cmd {
+ struct iwl_calib_cfg_status_s ucd_calib_cfg;
+ struct iwl_calib_cfg_status_s drv_calib_cfg;
+ __le32 reserved1;
+} __attribute__ ((packed));
+
+struct iwl5000_calib_hdr {
+ u8 op_code;
+ u8 first_group;
+ u8 groups_num;
+ u8 data_valid;
+} __attribute__ ((packed));
+
struct iwl5000_calibration_chain_noise_reset_cmd {
u8 op_code; /* IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
u8 flags; /* not used */
@@ -2894,6 +2943,7 @@ struct iwl_rx_packet {
struct iwl4965_notif_statistics stats;
struct iwl4965_compressed_ba_resp compressed_ba;
struct iwl4965_missed_beacon_notif missed_beacon;
+ struct iwl5000_calibration calib;
__le32 status;
u8 raw[0];
} u;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 373e984..010085a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -871,9 +871,25 @@ err:
}
EXPORT_SYMBOL(iwl_init_drv);

+void iwl_free_calib_results(struct iwl_priv *priv)
+{
+ kfree(priv->calib_results.lo_res);
+ priv->calib_results.lo_res = NULL;
+ priv->calib_results.lo_res_len = 0;
+
+ kfree(priv->calib_results.tx_iq_res);
+ priv->calib_results.tx_iq_res = NULL;
+ priv->calib_results.tx_iq_res_len = 0;
+
+ kfree(priv->calib_results.tx_iq_perd_res);
+ priv->calib_results.tx_iq_perd_res = NULL;
+ priv->calib_results.tx_iq_perd_res_len = 0;
+}
+EXPORT_SYMBOL(iwl_free_calib_results);

void iwl_uninit_drv(struct iwl_priv *priv)
{
+ iwl_free_calib_results(priv);
iwlcore_free_geos(priv);
iwl_free_channel_map(priv);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index eeea4e8..4fe7a9b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -172,6 +172,7 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
void iwl_hw_detect(struct iwl_priv *priv);

void iwlcore_clear_stations_table(struct iwl_priv *priv);
+void iwl_free_calib_results(struct iwl_priv *priv);
void iwl_reset_qos(struct iwl_priv *priv);
void iwl_set_rxon_chain(struct iwl_priv *priv);
int iwl_set_rxon_channel(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index d7bca7c..924a1f4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -877,6 +877,15 @@ struct statistics_general_data {
u32 beacon_energy_c;
};

+struct iwl_calib_results {
+ void *tx_iq_res;
+ void *tx_iq_perd_res;
+ void *lo_res;
+ u32 tx_iq_res_len;
+ u32 tx_iq_perd_res_len;
+ u32 lo_res_len;
+};
+
enum ucode_type {
UCODE_NONE = 0,
UCODE_INIT,
@@ -984,6 +993,9 @@ struct iwl_priv {
s32 temperature; /* degrees Kelvin */
s32 last_temperature;

+ /* init calibration results */
+ struct iwl_calib_results calib_results;
+
/* Scan related variables */
unsigned long last_scan_jiffies;
unsigned long next_scan_jiffies;
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index dc1f027..d3a2a5b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -146,6 +146,7 @@ struct iwl_eeprom_channel {

/*5000 calibrations */
#define EEPROM_5000_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
+#define EEPROM_5000_XTAL ((2*0x128) | EEPROM_5000_CALIB_ALL)

/* 5000 links */
#define EEPROM_5000_LINK_HOST (2*0x64)
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index dab4a0e..6c53736 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -56,6 +56,7 @@ const char *get_cmd_string(u8 cmd)
IWL_CMD(REPLY_RATE_SCALE);
IWL_CMD(REPLY_LEDS_CMD);
IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
+ IWL_CMD(COEX_PRIORITY_TABLE_CMD);
IWL_CMD(RADAR_NOTIFICATION);
IWL_CMD(REPLY_QUIET_CMD);
IWL_CMD(REPLY_CHANNEL_SWITCH);
@@ -89,6 +90,9 @@ const char *get_cmd_string(u8 cmd)
IWL_CMD(REPLY_RX_MPDU_CMD);
IWL_CMD(REPLY_RX);
IWL_CMD(REPLY_COMPRESSED_BA);
+ IWL_CMD(CALIBRATION_CFG_CMD);
+ IWL_CMD(CALIBRATION_RES_NOTIFICATION);
+ IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
default:
return "UNKNOWN";

--
1.5.3.6


2008-05-23 02:11:21

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: don't switch to SGI if not supported by AP

From: Emmanuel Grumbach <[email protected]>

This patch fixes SGI support. RS didn't look at the capabilities of the AP
before switching to SGI, this should lead to a stall in the traffic with an
AP that doesn't support SGI.

Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Guy Cohen <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 18 ++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ++--
drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 ++--
3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index 071c7b6..2adc228 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -1439,6 +1439,15 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
}
break;
case IWL_SISO_SWITCH_GI:
+ if (!tbl->is_fat &&
+ !(priv->current_ht_config.sgf &
+ HT_SHORT_GI_20MHZ))
+ break;
+ if (tbl->is_fat &&
+ !(priv->current_ht_config.sgf &
+ HT_SHORT_GI_40MHZ))
+ break;
+
IWL_DEBUG_RATE("LQ: SISO toggle SGI/NGI\n");

memcpy(search_tbl, tbl, sz);
@@ -1521,6 +1530,15 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
break;

case IWL_MIMO_SWITCH_GI:
+ if (!tbl->is_fat &&
+ !(priv->current_ht_config.sgf &
+ HT_SHORT_GI_20MHZ))
+ break;
+ if (tbl->is_fat &&
+ !(priv->current_ht_config.sgf &
+ HT_SHORT_GI_40MHZ))
+ break;
+
IWL_DEBUG_RATE("LQ: MIMO toggle SGI/NGI\n");

/* Set up new search table for MIMO */
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 4106efd..7a54682 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -610,8 +610,8 @@ struct iwl_hw_params {
#endif
};

-#define HT_SHORT_GI_20MHZ_ONLY (1 << 0)
-#define HT_SHORT_GI_40MHZ_ONLY (1 << 1)
+#define HT_SHORT_GI_20MHZ (1 << 0)
+#define HT_SHORT_GI_40MHZ (1 << 1)


#define IWL_RX_HDR(x) ((struct iwl4965_rx_frame_hdr *)(\
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index dd2fd40..a532a9e 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -700,9 +700,9 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);

if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
- iwl_conf->sgf |= 0x1;
+ iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
- iwl_conf->sgf |= 0x2;
+ iwl_conf->sgf |= HT_SHORT_GI_40MHZ;

iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
iwl_conf->max_amsdu_size =
--
1.5.3.6


2008-05-23 02:11:56

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: refactor stop master function

From: Tomas Winkler <[email protected]>

This patch refactors stop master function for 4965 and 5000.
Currently it duplicates the function.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 60 +++++++++++++------------------
drivers/net/wireless/iwlwifi/iwl-5000.c | 29 ++++++++++++++-
drivers/net/wireless/iwlwifi/iwl-dev.h | 1 -
3 files changed, 52 insertions(+), 38 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 378fd83..c10ac72 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -583,39 +583,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}

-int iwl4965_hw_nic_stop_master(struct iwl_priv *priv)
-{
- int rc = 0;
- u32 reg_val;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* set stop master bit */
- iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
-
- reg_val = iwl_read32(priv, CSR_GP_CNTRL);
-
- if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE ==
- (reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE))
- IWL_DEBUG_INFO("Card in power save, master is already "
- "stopped\n");
- else {
- rc = iwl_poll_bit(priv, CSR_RESET,
- CSR_RESET_REG_FLAG_MASTER_DISABLED,
- CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
- if (rc < 0) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
- }
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
- IWL_DEBUG_INFO("stop master\n");
-
- return rc;
-}
-
/**
* iwl4965_hw_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory
*/
@@ -646,11 +613,34 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
iwl_hw_txq_ctx_free(priv);
}

+static int iwl4965_apm_stop_master(struct iwl_priv *priv)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* set stop master bit */
+ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+
+ ret = iwl_poll_bit(priv, CSR_RESET,
+ CSR_RESET_REG_FLAG_MASTER_DISABLED,
+ CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
+ if (ret < 0)
+ goto out;
+
+out:
+ spin_unlock_irqrestore(&priv->lock, flags);
+ IWL_DEBUG_INFO("stop master\n");
+
+ return ret;
+}
+
static void iwl4965_apm_stop(struct iwl_priv *priv)
{
unsigned long flags;

- iwl4965_hw_nic_stop_master(priv);
+ iwl4965_apm_stop_master(priv);

spin_lock_irqsave(&priv->lock, flags);

@@ -667,7 +657,7 @@ static int iwl4965_apm_reset(struct iwl_priv *priv)
int ret = 0;
unsigned long flags;

- iwl4965_hw_nic_stop_master(priv);
+ iwl4965_apm_stop_master(priv);

spin_lock_irqsave(&priv->lock, flags);

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 27cfe3c..d607452 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -56,6 +56,31 @@ static const u16 iwl5000_default_queue_to_tx_fifo[] = {
IWL_TX_FIFO_HCCA_2
};

+/* FIXME: same implementation as 4965 */
+static int iwl5000_apm_stop_master(struct iwl_priv *priv)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* set stop master bit */
+ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+
+ ret = iwl_poll_bit(priv, CSR_RESET,
+ CSR_RESET_REG_FLAG_MASTER_DISABLED,
+ CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
+ if (ret < 0)
+ goto out;
+
+out:
+ spin_unlock_irqrestore(&priv->lock, flags);
+ IWL_DEBUG_INFO("stop master\n");
+
+ return ret;
+}
+
+
static int iwl5000_apm_init(struct iwl_priv *priv)
{
int ret = 0;
@@ -105,7 +130,7 @@ static void iwl5000_apm_stop(struct iwl_priv *priv)
{
unsigned long flags;

- iwl4965_hw_nic_stop_master(priv);
+ iwl5000_apm_stop_master(priv);

spin_lock_irqsave(&priv->lock, flags);

@@ -124,7 +149,7 @@ static int iwl5000_apm_reset(struct iwl_priv *priv)
int ret = 0;
unsigned long flags;

- iwl4965_hw_nic_stop_master(priv);
+ iwl5000_apm_stop_master(priv);

spin_lock_irqsave(&priv->lock, flags);

diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 38bd497..dfbf728 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -687,7 +687,6 @@ extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv);
extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv);
extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
-extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv);
extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv);
extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
--
1.5.3.6


2008-05-23 05:59:32

by Tomas Winkler

[permalink] [raw]
Subject: Re: [PATCH] iwlwifi: impelemnt 5000 tx response path

On Fri, May 23, 2008 at 8:44 AM, Harvey Harrison
<[email protected]> wrote:
> On Fri, 2008-05-23 at 10:09 +0800, Zhu Yi wrote:
>> From: Ron Rindjunsky <[email protected]>
>>
>> This patch implements 5000 HW tx response path
>>
>> Signed-off-by: Ron Rindjunsky <[email protected]>
>> ---
>> drivers/net/wireless/iwlwifi/iwl-5000.c | 235 +++++++++++++++++++++++++++++++
>> net/mac80211/mlme.c | 10 +-
>> 2 files changed, 240 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
>> index 685a84e..5d6a28c 100644
>> --- a/drivers/net/wireless/iwlwifi/iwl-5000.c
>> +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
>> @@ -972,6 +972,240 @@ static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
>> iwl_write_prph(priv, IWL50_SCD_TXFACT, mask);
>> }
>>
>> +
>> +static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp)
>> +{
>> + __le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status +
>> + tx_resp->frame_count);
>> + return le32_to_cpu(*scd_ssn) & MAX_SN;
>
> How about:
>
> return le32_to_cpup((__le32 *)&tx_resp->status + tx_resp->frame_count);
>
> Cheers,
>
> Harvey
>

Thanks
Will apply on top of it
return le32_to_cpup((__le32 *)&tx_resp->status +
tx_resp->frame_count) & MAX_SN;

Thank
Tomas

2008-05-23 02:11:30

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: iwl5000 WiFi/WiMax coexistence

From: Ron Rindjunsky <[email protected]>

This patch adds WiFi/WiMax coexistence to iwl5000.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-5000.c | 12 ++++++
drivers/net/wireless/iwlwifi/iwl-commands.h | 54 +++++++++++++++++++++++++++
2 files changed, 66 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 5e818ee..520c7ea 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -494,6 +494,16 @@ static void iwl5000_tx_queue_set_status(struct iwl_priv *priv,
scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
}

+static int iwl5000_send_wimax_coex(struct iwl_priv *priv)
+{
+ struct iwl_wimax_coex_cmd coex_cmd;
+
+ memset(&coex_cmd, 0, sizeof(coex_cmd));
+
+ return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD,
+ sizeof(coex_cmd), &coex_cmd);
+}
+
static int iwl5000_alive_notify(struct iwl_priv *priv)
{
u32 a;
@@ -568,6 +578,8 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);

+ iwl5000_send_wimax_coex(priv);
+
/* Ask for statistics now, the uCode will send notification
* periodically after association */
iwl_send_statistics_request(priv, CMD_ASYNC);
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index dd84326..5b9e9bf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -93,6 +93,11 @@ enum {
REPLY_LEDS_CMD = 0x48,
REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */

+ /* WiMAX coexistence */
+ COEX_PRIORITY_TABLE_CMD = 0x5a, /*5000 only */
+ COEX_MEDIUM_NOTIFICATION = 0x5b,
+ COEX_EVENT_CMD = 0x5c,
+
/* 802.11h related */
RADAR_NOTIFICATION = 0x70, /* not used */
REPLY_QUIET_CMD = 0x71, /* not used */
@@ -2797,6 +2802,55 @@ struct iwl4965_led_cmd {
u8 reserved;
} __attribute__ ((packed));

+/*
+ * Coexistence WIFI/WIMAX Command
+ * COEX_PRIORITY_TABLE_CMD = 0x5a
+ *
+ */
+enum {
+ COEX_UNASSOC_IDLE = 0,
+ COEX_UNASSOC_MANUAL_SCAN = 1,
+ COEX_UNASSOC_AUTO_SCAN = 2,
+ COEX_CALIBRATION = 3,
+ COEX_PERIODIC_CALIBRATION = 4,
+ COEX_CONNECTION_ESTAB = 5,
+ COEX_ASSOCIATED_IDLE = 6,
+ COEX_ASSOC_MANUAL_SCAN = 7,
+ COEX_ASSOC_AUTO_SCAN = 8,
+ COEX_ASSOC_ACTIVE_LEVEL = 9,
+ COEX_RF_ON = 10,
+ COEX_RF_OFF = 11,
+ COEX_STAND_ALONE_DEBUG = 12,
+ COEX_IPAN_ASSOC_LEVEL = 13,
+ COEX_RSRVD1 = 14,
+ COEX_RSRVD2 = 15,
+ COEX_NUM_OF_EVENTS = 16
+};
+
+struct iwl_wimax_coex_event_entry {
+ u8 request_prio;
+ u8 win_medium_prio;
+ u8 reserved;
+ u8 flags;
+} __attribute__ ((packed));
+
+/* COEX flag masks */
+
+/* Staion table is valid */
+#define COEX_FLAGS_STA_TABLE_VALID_MSK (0x1)
+/* UnMask wakeup src at unassociated sleep */
+#define COEX_FLAGS_UNASSOC_WA_UNMASK_MSK (0x4)
+/* UnMask wakeup src at associated sleep */
+#define COEX_FLAGS_ASSOC_WA_UNMASK_MSK (0x8)
+/* Enable CoEx feature. */
+#define COEX_FLAGS_COEX_ENABLE_MSK (0x80)
+
+struct iwl_wimax_coex_cmd {
+ u8 flags;
+ u8 reserved[3];
+ struct iwl_wimax_coex_event_entry sta_prio[COEX_NUM_OF_EVENTS];
+} __attribute__ ((packed));
+
/******************************************************************************
* (13)
* Union of all expected notifications/responses:
--
1.5.3.6


2008-05-23 02:11:58

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: move iwl_rxq_stop into iwl-rx.c

From: Tomas Winkler <[email protected]>

This patch moves iwl_rxq_stop into iwl-rx.c.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 25 -------------------------
drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +-
drivers/net/wireless/iwlwifi/iwl-rx.c | 26 ++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 +-
4 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 0c3664f..da08622 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -388,31 +388,6 @@ void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
&priv->bands[IEEE80211_BAND_2GHZ].bitrates[rate_index];
}

-int iwl4965_hw_rxq_stop(struct iwl_priv *priv)
-{
- int rc;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_nic_access(priv);
- if (rc) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
- }
-
- /* stop Rx DMA */
- iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
- rc = iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
- (1 << 24), 1000);
- if (rc < 0)
- IWL_ERROR("Can't stop Rx DMA.\n");
-
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
/*
* EEPROM handlers
*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 1fc4d9a..def1461 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -685,8 +685,8 @@ extern u8 iwl4965_sync_station(struct iwl_priv *priv, int sta_id,
****************************************************************************/
extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv);
extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv);
-extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
+extern int iwl_rxq_stop(struct iwl_priv *priv);
extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index a2eb90d..ed63e5c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -420,3 +420,29 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
return 0;
}

+int iwl_rxq_stop(struct iwl_priv *priv)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ret = iwl_grab_nic_access(priv);
+ if (unlikely(ret)) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
+ }
+
+ /* stop Rx DMA */
+ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+ ret = iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
+ (1 << 24), 1000);
+ if (ret < 0)
+ IWL_ERROR("Can't stop Rx DMA.\n");
+
+ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(iwl_rxq_stop);
+
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 14b55ec..b47d8be 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -3413,7 +3413,7 @@ static void __iwl4965_down(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);

iwl_txq_ctx_stop(priv);
- iwl4965_hw_rxq_stop(priv);
+ iwl_rxq_stop(priv);

spin_lock_irqsave(&priv->lock, flags);
if (!iwl_grab_nic_access(priv)) {
--
1.5.3.6


2008-05-23 02:11:13

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: remove 4965 from iwl4965_rate_info

From: Tomas Winkler <[email protected]>

This patch removes 4965 from iwl4965_rate_info structure and
associated variables.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 27 ++++++++++++++-------------
drivers/net/wireless/iwlwifi/iwl-4965-rs.h | 8 ++++----
drivers/net/wireless/iwlwifi/iwl-4965.c | 12 ++++++------
drivers/net/wireless/iwlwifi/iwl-core.c | 8 ++++----
drivers/net/wireless/iwlwifi/iwl4965-base.c | 6 +++---
5 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index 8e3660e..e2123ab 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -481,7 +481,7 @@ static u32 rate_n_flags_from_tbl(struct iwl4965_scale_tbl_info *tbl,
u32 rate_n_flags = 0;

if (is_legacy(tbl->lq_type)) {
- rate_n_flags = iwl4965_rates[index].plcp;
+ rate_n_flags = iwl_rates[index].plcp;
if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE)
rate_n_flags |= RATE_MCS_CCK_MSK;

@@ -493,11 +493,11 @@ static u32 rate_n_flags_from_tbl(struct iwl4965_scale_tbl_info *tbl,
rate_n_flags = RATE_MCS_HT_MSK;

if (is_siso(tbl->lq_type))
- rate_n_flags |= iwl4965_rates[index].plcp_siso;
+ rate_n_flags |= iwl_rates[index].plcp_siso;
else if (is_mimo2(tbl->lq_type))
- rate_n_flags |= iwl4965_rates[index].plcp_mimo2;
+ rate_n_flags |= iwl_rates[index].plcp_mimo2;
else
- rate_n_flags |= iwl4965_rates[index].plcp_mimo3;
+ rate_n_flags |= iwl_rates[index].plcp_mimo3;
} else {
IWL_ERROR("Invalid tbl->lq_type %d\n", tbl->lq_type);
}
@@ -697,7 +697,7 @@ static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask,

low = index;
while (low != IWL_RATE_INVALID) {
- low = iwl4965_rates[low].prev_rs;
+ low = iwl_rates[low].prev_rs;
if (low == IWL_RATE_INVALID)
break;
if (rate_mask & (1 << low))
@@ -707,7 +707,7 @@ static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask,

high = index;
while (high != IWL_RATE_INVALID) {
- high = iwl4965_rates[high].next_rs;
+ high = iwl_rates[high].next_rs;
if (high == IWL_RATE_INVALID)
break;
if (rate_mask & (1 << high))
@@ -2088,7 +2088,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
i = 0;

/* FIXME:RS: This is also wrong in 4965 */
- rate = iwl4965_rates[i].plcp;
+ rate = iwl_rates[i].plcp;
rate |= RATE_MCS_ANT_B_MSK;
rate &= ~RATE_MCS_ANT_A_MSK;

@@ -2691,7 +2691,7 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
int active = lq_sta->active_tbl;

cnt +=
- sprintf(&buf[cnt], " %2dMbs: ", iwl4965_rates[i].ieee / 2);
+ sprintf(&buf[cnt], " %2dMbs: ", iwl_rates[i].ieee / 2);

mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1));
for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1)
@@ -2702,7 +2702,7 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
samples += lq_sta->lq_info[active].win[i].counter;
good += lq_sta->lq_info[active].win[i].success_counter;
success += lq_sta->lq_info[active].win[i].success_counter *
- iwl4965_rates[i].ieee;
+ iwl_rates[i].ieee;

if (lq_sta->lq_info[active].win[i].stamp) {
int delta =
@@ -2722,10 +2722,11 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
i = j;
}

- /* Display the average rate of all samples taken.
- *
- * NOTE: We multiply # of samples by 2 since the IEEE measurement
- * added from iwl4965_rates is actually 2X the rate */
+ /*
+ * Display the average rate of all samples taken.
+ * NOTE: We multiply # of samples by 2 since the IEEE measurement
+ * added from iwl_rates is actually 2X the rate.
+ */
if (samples)
cnt += sprintf(&buf[cnt],
"\nAverage rate is %3d.%02dMbs over last %4dms\n"
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
index 7ea2041..1dd4124 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
@@ -29,7 +29,7 @@

#include "iwl-dev.h"

-struct iwl4965_rate_info {
+struct iwl_rate_info {
u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */
u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */
u8 plcp_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */
@@ -45,7 +45,7 @@ struct iwl4965_rate_info {

/*
* These serve as indexes into
- * struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT];
+ * struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
*/
enum {
IWL_RATE_1M_INDEX = 0,
@@ -240,7 +240,7 @@ enum {
#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))

-extern const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT];
+extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];

enum iwl_table_type {
LQ_NONE,
@@ -279,7 +279,7 @@ static inline u8 num_of_ant(u8 mask)

static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index)
{
- u8 rate = iwl4965_rates[rate_index].prev_ieee;
+ u8 rate = iwl_rates[rate_index].prev_ieee;

if (rate == IWL_RATE_INVALID)
rate = rate_index;
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 922b0a1..1ec53a3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -345,8 +345,8 @@ int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags)

/* 4965 legacy rate format, search for match in table */
} else {
- for (idx = 0; idx < ARRAY_SIZE(iwl4965_rates); idx++)
- if (iwl4965_rates[idx].plcp == (rate_n_flags & 0xFF))
+ for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++)
+ if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
return idx;
}

@@ -1951,7 +1951,7 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
u16 rate_flags = 0;
int rate_idx = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);

- rate_plcp = iwl4965_rates[rate_idx].plcp;
+ rate_plcp = iwl_rates[rate_idx].plcp;

rts_retry_limit = (is_hcca) ?
RTS_HCCA_RETRY_LIMIT : RTS_DFAULT_RETRY_LIMIT;
@@ -2436,7 +2436,7 @@ static void iwl4965_add_radiotap(struct iwl_priv *priv,
if (rate == -1)
iwl4965_rt->rt_rate = 0;
else
- iwl4965_rt->rt_rate = iwl4965_rates[rate].ieee;
+ iwl4965_rt->rt_rate = iwl_rates[rate].ieee;

/*
* "antenna number"
@@ -2848,7 +2848,7 @@ static void iwl4965_dbg_report_frame(struct iwl_priv *priv,
if (unlikely(rate_idx == -1))
bitrate = 0;
else
- bitrate = iwl4965_rates[rate_idx].ieee / 2;
+ bitrate = iwl_rates[rate_idx].ieee / 2;

/* print frame summary.
* MAC addresses show just the last byte (for brevity),
@@ -3473,7 +3473,7 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
rate_flags |= RATE_MCS_ANT_B_MSK; /*FIXME:RS*/

link_cmd.rs_table[i].rate_n_flags =
- iwl4965_hw_set_rate_n_flags(iwl4965_rates[r].plcp, rate_flags);
+ iwl4965_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
r = iwl4965_get_prev_ieee_rate(r);
}

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index b800031..8e411de 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -67,7 +67,7 @@ MODULE_LICENSE("GPL");
* maps to IWL_RATE_INVALID
*
*/
-const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT] = {
+const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2), /* 1mbps */
IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5), /* 2mbps */
IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11), /*5.5mbps */
@@ -83,7 +83,7 @@ const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT] = {
IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
/* FIXME:RS: ^^ should be INV (legacy) */
};
-EXPORT_SYMBOL(iwl4965_rates);
+EXPORT_SYMBOL(iwl_rates);

/* This function both allocates and initializes hw and priv. */
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
@@ -383,7 +383,7 @@ static void iwlcore_init_hw_rates(struct iwl_priv *priv,
int i;

for (i = 0; i < IWL_RATE_COUNT; i++) {
- rates[i].bitrate = iwl4965_rates[i].ieee * 5;
+ rates[i].bitrate = iwl_rates[i].ieee * 5;
rates[i].hw_value = i; /* Rate scaling will work on indexes */
rates[i].hw_value_short = i;
rates[i].flags = 0;
@@ -392,7 +392,7 @@ static void iwlcore_init_hw_rates(struct iwl_priv *priv,
* If CCK != 1M then set short preamble rate flag.
*/
rates[i].flags |=
- (iwl4965_rates[i].plcp == IWL_RATE_1M_PLCP) ?
+ (iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ?
0 : IEEE80211_RATE_SHORT_PREAMBLE;
}
}
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 1c45b6f..edde814 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -878,9 +878,9 @@ static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)

/* Find lowest valid rate */
for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
- i = iwl4965_rates[i].next_ieee) {
+ i = iwl_rates[i].next_ieee) {
if (rate_mask & (1 << i))
- return iwl4965_rates[i].plcp;
+ return iwl_rates[i].plcp;
}

/* No valid rate was found. Assign the lowest one */
@@ -939,7 +939,7 @@ static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate,
for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
if (bit & supported_rate) {
ret_rates |= bit;
- rates[*cnt] = iwl4965_rates[i].ieee |
+ rates[*cnt] = iwl_rates[i].ieee |
((bit & basic_rate) ? 0x80 : 0x00);
(*cnt)++;
(*left)--;
--
1.5.3.6


2008-05-23 02:11:15

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: move more station managment into iwl-sta.c

From: Tomas Winkler <[email protected]>

This patch moves station management functions into iwl-sta.c (iwlcore).

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 4 +-
drivers/net/wireless/iwlwifi/iwl-4965.c | 101 ----------
drivers/net/wireless/iwlwifi/iwl-dev.h | 8 +-
drivers/net/wireless/iwlwifi/iwl-sta.c | 269 +++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-sta.h | 2 +
drivers/net/wireless/iwlwifi/iwl4965-base.c | 178 +-----------------
6 files changed, 283 insertions(+), 279 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index e2123ab..ce70f2b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -2150,7 +2150,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE("LQ: ADD station %s\n",
print_mac(mac, hdr->addr1));
- sta_id = iwl4965_add_station_flags(priv, hdr->addr1,
+ sta_id = iwl_add_station_flags(priv, hdr->addr1,
0, CMD_ASYNC, NULL);
}
if ((sta_id != IWL_INVALID_STATION)) {
@@ -2234,7 +2234,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE("LQ: ADD station %s\n",
print_mac(mac, sta->addr));
- sta_id = iwl4965_add_station_flags(priv, sta->addr,
+ sta_id = iwl_add_station_flags(priv, sta->addr,
0, CMD_ASYNC, NULL);
}
if ((sta_id != IWL_INVALID_STATION)) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 44215a7..aeaf5f7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -3433,109 +3433,8 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id,

#endif /* CONFIG_IWL4965_HT */

-/**
- * iwl4965_add_station - Initialize a station's hardware rate table
- *
- * The uCode's station table contains a table of fallback rates
- * for automatic fallback during transmission.
- *
- * NOTE: This sets up a default set of values. These will be replaced later
- * if the driver's iwl-4965-rs rate scaling algorithm is used, instead of
- * rc80211_simple.
- *
- * NOTE: Run REPLY_ADD_STA command to set up station table entry, before
- * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
- * which requires station table entry to exist).
- */
-void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
-{
- int i, r;
- struct iwl_link_quality_cmd link_cmd = {
- .reserved1 = 0,
- };
- u16 rate_flags;
-
- /* Set up the rate scaling to start at selected rate, fall back
- * all the way down to 1M in IEEE order, and then spin on 1M */
- if (is_ap)
- r = IWL_RATE_54M_INDEX;
- else if (priv->band == IEEE80211_BAND_5GHZ)
- r = IWL_RATE_6M_INDEX;
- else
- r = IWL_RATE_1M_INDEX;
-
- for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
- rate_flags = 0;
- if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
- rate_flags |= RATE_MCS_CCK_MSK;
-
- /* Use Tx antenna B only */
- rate_flags |= RATE_MCS_ANT_B_MSK; /*FIXME:RS*/
-
- link_cmd.rs_table[i].rate_n_flags =
- iwl4965_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
- r = iwl4965_get_prev_ieee_rate(r);
- }
-
- link_cmd.general_params.single_stream_ant_msk = 2;
- link_cmd.general_params.dual_stream_ant_msk = 3;
- link_cmd.agg_params.agg_dis_start_th = 3;
- link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000);
-
- /* Update the rate scaling for control frame Tx to AP */
- link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id;
-
- iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD,
- sizeof(link_cmd), &link_cmd, NULL);
-}

#ifdef CONFIG_IWL4965_HT
-
-void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index,
- struct ieee80211_ht_info *sta_ht_inf)
-{
- __le32 sta_flags;
- u8 mimo_ps_mode;
-
- if (!sta_ht_inf || !sta_ht_inf->ht_supported)
- goto done;
-
- mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2;
-
- sta_flags = priv->stations[index].sta.station_flags;
-
- sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
-
- switch (mimo_ps_mode) {
- case WLAN_HT_CAP_MIMO_PS_STATIC:
- sta_flags |= STA_FLG_MIMO_DIS_MSK;
- break;
- case WLAN_HT_CAP_MIMO_PS_DYNAMIC:
- sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
- break;
- case WLAN_HT_CAP_MIMO_PS_DISABLED:
- break;
- default:
- IWL_WARNING("Invalid MIMO PS mode %d", mimo_ps_mode);
- break;
- }
-
- sta_flags |= cpu_to_le32(
- (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
-
- sta_flags |= cpu_to_le32(
- (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
-
- if (iwl_is_fat_tx_allowed(priv, sta_ht_inf))
- sta_flags |= STA_FLG_FAT_EN_MSK;
- else
- sta_flags &= ~STA_FLG_FAT_EN_MSK;
-
- priv->stations[index].sta.station_flags = sta_flags;
- done:
- return;
-}
-
static int iwl4965_rx_agg_start(struct iwl_priv *priv,
const u8 *addr, int tid, u16 ssn)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 8809fe3..565d7dc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -635,8 +635,8 @@ struct iwl_hw_params {
struct iwl_addsta_cmd;
extern int iwl_send_add_sta(struct iwl_priv *priv,
struct iwl_addsta_cmd *sta, u8 flags);
-extern u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
- int is_ap, u8 flags, void *ht_data);
+u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
+ u8 flags, struct ieee80211_ht_info *ht_info);
extern int iwl4965_is_network_packet(struct iwl_priv *priv,
struct ieee80211_hdr *header);
extern int iwl4965_power_init_handle(struct iwl_priv *priv);
@@ -731,8 +731,6 @@ extern void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio);
extern int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
u16 byte_cnt);
-extern void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr,
- int is_ap);
extern int iwl4965_alive_notify(struct iwl_priv *priv);
extern void iwl4965_update_rate_scaling(struct iwl_priv *priv, u8 mode);
extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv);
@@ -746,8 +744,6 @@ extern void iwl4965_init_ht_hw_capab(const struct iwl_priv *priv,
enum ieee80211_band band);
void iwl4965_set_rxon_ht(struct iwl_priv *priv,
struct iwl_ht_info *ht_info);
-void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index,
- struct ieee80211_ht_info *sta_ht_inf);
int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
const u8 *addr, u16 tid, u16 *ssn);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index f226704..c8e468f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -117,6 +117,130 @@ int iwl_send_add_sta(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_send_add_sta);

+#ifdef CONFIG_IWL4965_HT
+
+static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
+ struct ieee80211_ht_info *sta_ht_inf)
+{
+ __le32 sta_flags;
+ u8 mimo_ps_mode;
+
+ if (!sta_ht_inf || !sta_ht_inf->ht_supported)
+ goto done;
+
+ mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2;
+
+ sta_flags = priv->stations[index].sta.station_flags;
+
+ sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
+
+ switch (mimo_ps_mode) {
+ case WLAN_HT_CAP_MIMO_PS_STATIC:
+ sta_flags |= STA_FLG_MIMO_DIS_MSK;
+ break;
+ case WLAN_HT_CAP_MIMO_PS_DYNAMIC:
+ sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
+ break;
+ case WLAN_HT_CAP_MIMO_PS_DISABLED:
+ break;
+ default:
+ IWL_WARNING("Invalid MIMO PS mode %d", mimo_ps_mode);
+ break;
+ }
+
+ sta_flags |= cpu_to_le32(
+ (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
+
+ sta_flags |= cpu_to_le32(
+ (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
+
+ if (iwl_is_fat_tx_allowed(priv, sta_ht_inf))
+ sta_flags |= STA_FLG_FAT_EN_MSK;
+ else
+ sta_flags &= ~STA_FLG_FAT_EN_MSK;
+
+ priv->stations[index].sta.station_flags = sta_flags;
+ done:
+ return;
+}
+#else
+static inline void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
+ struct ieee80211_ht_info *sta_ht_info)
+{
+}
+#endif
+
+/**
+ * iwl_add_station_flags - Add station to tables in driver and device
+ */
+u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
+ u8 flags, struct ieee80211_ht_info *ht_info)
+{
+ int i;
+ int index = IWL_INVALID_STATION;
+ struct iwl_station_entry *station;
+ unsigned long flags_spin;
+ DECLARE_MAC_BUF(mac);
+
+ spin_lock_irqsave(&priv->sta_lock, flags_spin);
+ if (is_ap)
+ index = IWL_AP_ID;
+ else if (is_broadcast_ether_addr(addr))
+ index = priv->hw_params.bcast_sta_id;
+ else
+ for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
+ if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
+ addr)) {
+ index = i;
+ break;
+ }
+
+ if (!priv->stations[i].used &&
+ index == IWL_INVALID_STATION)
+ index = i;
+ }
+
+
+ /* These two conditions have the same outcome, but keep them separate
+ since they have different meanings */
+ if (unlikely(index == IWL_INVALID_STATION)) {
+ spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+ return index;
+ }
+
+ if (priv->stations[index].used &&
+ !compare_ether_addr(priv->stations[index].sta.sta.addr, addr)) {
+ spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+ return index;
+ }
+
+
+ IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr));
+ station = &priv->stations[index];
+ station->used = 1;
+ priv->num_stations++;
+
+ /* Set up the REPLY_ADD_STA command to send to device */
+ memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
+ memcpy(station->sta.sta.addr, addr, ETH_ALEN);
+ station->sta.mode = 0;
+ station->sta.sta.sta_id = index;
+ station->sta.station_flags = 0;
+
+ /* BCAST station and IBSS stations do not work in HT mode */
+ if (index != priv->hw_params.bcast_sta_id &&
+ priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
+ iwl_set_ht_add_station(priv, index, ht_info);
+
+ spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
+ /* Add station to device's station table */
+ iwl_send_add_sta(priv, &station->sta, flags);
+ return index;
+
+}
+EXPORT_SYMBOL(iwl_add_station_flags);
+
int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
{
int i;
@@ -470,3 +594,148 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_send_lq_cmd);

+/**
+ * iwl_sta_init_lq - Initialize a station's hardware rate table
+ *
+ * The uCode's station table contains a table of fallback rates
+ * for automatic fallback during transmission.
+ *
+ * NOTE: This sets up a default set of values. These will be replaced later
+ * if the driver's iwl-4965-rs rate scaling algorithm is used, instead of
+ * rc80211_simple.
+ *
+ * NOTE: Run REPLY_ADD_STA command to set up station table entry, before
+ * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
+ * which requires station table entry to exist).
+ */
+static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
+{
+ int i, r;
+ struct iwl_link_quality_cmd link_cmd = {
+ .reserved1 = 0,
+ };
+ u16 rate_flags;
+
+ /* Set up the rate scaling to start at selected rate, fall back
+ * all the way down to 1M in IEEE order, and then spin on 1M */
+ if (is_ap)
+ r = IWL_RATE_54M_INDEX;
+ else if (priv->band == IEEE80211_BAND_5GHZ)
+ r = IWL_RATE_6M_INDEX;
+ else
+ r = IWL_RATE_1M_INDEX;
+
+ for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+ rate_flags = 0;
+ if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
+ rate_flags |= RATE_MCS_CCK_MSK;
+
+ /* Use Tx antenna B only */
+ rate_flags |= RATE_MCS_ANT_B_MSK; /*FIXME:RS*/
+
+ link_cmd.rs_table[i].rate_n_flags =
+ iwl4965_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
+ r = iwl4965_get_prev_ieee_rate(r);
+ }
+
+ link_cmd.general_params.single_stream_ant_msk = 2;
+ link_cmd.general_params.dual_stream_ant_msk = 3;
+ link_cmd.agg_params.agg_dis_start_th = 3;
+ link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000);
+
+ /* Update the rate scaling for control frame Tx to AP */
+ link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id;
+
+ iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD,
+ sizeof(link_cmd), &link_cmd, NULL);
+}
+/**
+ * iwl_rxon_add_station - add station into station table.
+ *
+ * there is only one AP station with id= IWL_AP_ID
+ * NOTE: mutex must be held before calling this fnction
+ */
+int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+{
+ u8 sta_id;
+
+ /* Add station to device's station table */
+#ifdef CONFIG_IWL4965_HT
+ struct ieee80211_conf *conf = &priv->hw->conf;
+ struct ieee80211_ht_info *cur_ht_config = &conf->ht_conf;
+
+ if ((is_ap) &&
+ (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
+ (priv->iw_mode == IEEE80211_IF_TYPE_STA))
+ sta_id = iwl_add_station_flags(priv, addr, is_ap,
+ 0, cur_ht_config);
+ else
+#endif /* CONFIG_IWL4965_HT */
+ sta_id = iwl_add_station_flags(priv, addr, is_ap,
+ 0, NULL);
+
+ /* Set up default rate scaling table in device's station table */
+ iwl_sta_init_lq(priv, addr, is_ap);
+
+ return sta_id;
+}
+EXPORT_SYMBOL(iwl_rxon_add_station);
+
+
+/**
+ * iwl_get_sta_id - Find station's index within station table
+ *
+ * If new IBSS station, create new entry in station table
+ */
+int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
+{
+ int sta_id;
+ u16 fc = le16_to_cpu(hdr->frame_control);
+ DECLARE_MAC_BUF(mac);
+
+ /* If this frame is broadcast or management, use broadcast station id */
+ if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
+ is_multicast_ether_addr(hdr->addr1))
+ return priv->hw_params.bcast_sta_id;
+
+ switch (priv->iw_mode) {
+
+ /* If we are a client station in a BSS network, use the special
+ * AP station entry (that's the only station we communicate with) */
+ case IEEE80211_IF_TYPE_STA:
+ return IWL_AP_ID;
+
+ /* If we are an AP, then find the station, or use BCAST */
+ case IEEE80211_IF_TYPE_AP:
+ sta_id = iwl_find_station(priv, hdr->addr1);
+ if (sta_id != IWL_INVALID_STATION)
+ return sta_id;
+ return priv->hw_params.bcast_sta_id;
+
+ /* If this frame is going out to an IBSS network, find the station,
+ * or create a new station table entry */
+ case IEEE80211_IF_TYPE_IBSS:
+ sta_id = iwl_find_station(priv, hdr->addr1);
+ if (sta_id != IWL_INVALID_STATION)
+ return sta_id;
+
+ /* Create new station table entry */
+ sta_id = iwl_add_station_flags(priv, hdr->addr1,
+ 0, CMD_ASYNC, NULL);
+
+ if (sta_id != IWL_INVALID_STATION)
+ return sta_id;
+
+ IWL_DEBUG_DROP("Station %s not in station map. "
+ "Defaulting to broadcast...\n",
+ print_mac(mac, hdr->addr1));
+ iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
+ return priv->hw_params.bcast_sta_id;
+
+ default:
+ IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
+ return priv->hw_params.bcast_sta_id;
+ }
+}
+EXPORT_SYMBOL(iwl_get_sta_id);
+
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 38b1b0a..ee25643 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -39,4 +39,6 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key, u8 sta_id);
int iwl_remove_dynamic_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key, u8 sta_id);
+int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
+int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
#endif /* __iwl_sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index bb820f3..88032cc 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -258,79 +258,6 @@ out:
}
#endif

-/**
- * iwl4965_add_station_flags - Add station to tables in driver and device
- */
-u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
- int is_ap, u8 flags, void *ht_data)
-{
- int i;
- int index = IWL_INVALID_STATION;
- struct iwl_station_entry *station;
- unsigned long flags_spin;
- DECLARE_MAC_BUF(mac);
-
- spin_lock_irqsave(&priv->sta_lock, flags_spin);
- if (is_ap)
- index = IWL_AP_ID;
- else if (is_broadcast_ether_addr(addr))
- index = priv->hw_params.bcast_sta_id;
- else
- for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
- if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
- addr)) {
- index = i;
- break;
- }
-
- if (!priv->stations[i].used &&
- index == IWL_INVALID_STATION)
- index = i;
- }
-
-
- /* These two conditions have the same outcome, but keep them separate
- since they have different meanings */
- if (unlikely(index == IWL_INVALID_STATION)) {
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- return index;
- }
-
- if (priv->stations[index].used &&
- !compare_ether_addr(priv->stations[index].sta.sta.addr, addr)) {
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- return index;
- }
-
-
- IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr));
- station = &priv->stations[index];
- station->used = 1;
- priv->num_stations++;
-
- /* Set up the REPLY_ADD_STA command to send to device */
- memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
- memcpy(station->sta.sta.addr, addr, ETH_ALEN);
- station->sta.mode = 0;
- station->sta.sta.sta_id = index;
- station->sta.station_flags = 0;
-
-#ifdef CONFIG_IWL4965_HT
- /* BCAST station and IBSS stations do not work in HT mode */
- if (index != priv->hw_params.bcast_sta_id &&
- priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
- iwl4965_set_ht_add_station(priv, index,
- (struct ieee80211_ht_info *) ht_data);
-#endif /*CONFIG_IWL4965_HT*/
-
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-
- /* Add station to device's station table */
- iwl_send_add_sta(priv, &station->sta, flags);
- return index;
-
-}
-


/*************** HOST COMMAND QUEUE FUNCTIONS *****/
@@ -434,38 +361,6 @@ static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
}

/**
- * iwl4965_rxon_add_station - add station into station table.
- *
- * there is only one AP station with id= IWL_AP_ID
- * NOTE: mutex must be held before calling this fnction
- */
-static int iwl4965_rxon_add_station(struct iwl_priv *priv,
- const u8 *addr, int is_ap)
-{
- u8 sta_id;
-
- /* Add station to device's station table */
-#ifdef CONFIG_IWL4965_HT
- struct ieee80211_conf *conf = &priv->hw->conf;
- struct ieee80211_ht_info *cur_ht_config = &conf->ht_conf;
-
- if ((is_ap) &&
- (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
- (priv->iw_mode == IEEE80211_IF_TYPE_STA))
- sta_id = iwl4965_add_station_flags(priv, addr, is_ap,
- 0, cur_ht_config);
- else
-#endif /* CONFIG_IWL4965_HT */
- sta_id = iwl4965_add_station_flags(priv, addr, is_ap,
- 0, NULL);
-
- /* Set up default rate scaling table in device's station table */
- iwl4965_add_station(priv, addr, is_ap);
-
- return sta_id;
-}
-
-/**
* iwl4965_check_rxon_cmd - validate RXON structure is valid
*
* NOTE: This is really only useful during development and can eventually
@@ -691,7 +586,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
}

/* Add the broadcast address so we can send broadcast frames */
- if (iwl4965_rxon_add_station(priv, iwl_bcast_addr, 0) ==
+ if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
IWL_INVALID_STATION) {
IWL_ERROR("Error adding BROADCAST address for transmit.\n");
return -EIO;
@@ -701,7 +596,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
* add the IWL_AP_ID to the station rate table */
if (iwl_is_associated(priv) &&
(priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
- if (iwl4965_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
+ if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
== IWL_INVALID_STATION) {
IWL_ERROR("Error adding AP address for transmit.\n");
return -EIO;
@@ -1702,63 +1597,6 @@ static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len)
priv->tx_stats[idx].cnt++;
priv->tx_stats[idx].bytes += len;
}
-/**
- * iwl4965_get_sta_id - Find station's index within station table
- *
- * If new IBSS station, create new entry in station table
- */
-static int iwl4965_get_sta_id(struct iwl_priv *priv,
- struct ieee80211_hdr *hdr)
-{
- int sta_id;
- u16 fc = le16_to_cpu(hdr->frame_control);
- DECLARE_MAC_BUF(mac);
-
- /* If this frame is broadcast or management, use broadcast station id */
- if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
- is_multicast_ether_addr(hdr->addr1))
- return priv->hw_params.bcast_sta_id;
-
- switch (priv->iw_mode) {
-
- /* If we are a client station in a BSS network, use the special
- * AP station entry (that's the only station we communicate with) */
- case IEEE80211_IF_TYPE_STA:
- return IWL_AP_ID;
-
- /* If we are an AP, then find the station, or use BCAST */
- case IEEE80211_IF_TYPE_AP:
- sta_id = iwl_find_station(priv, hdr->addr1);
- if (sta_id != IWL_INVALID_STATION)
- return sta_id;
- return priv->hw_params.bcast_sta_id;
-
- /* If this frame is going out to an IBSS network, find the station,
- * or create a new station table entry */
- case IEEE80211_IF_TYPE_IBSS:
- sta_id = iwl_find_station(priv, hdr->addr1);
- if (sta_id != IWL_INVALID_STATION)
- return sta_id;
-
- /* Create new station table entry */
- sta_id = iwl4965_add_station_flags(priv, hdr->addr1,
- 0, CMD_ASYNC, NULL);
-
- if (sta_id != IWL_INVALID_STATION)
- return sta_id;
-
- IWL_DEBUG_DROP("Station %s not in station map. "
- "Defaulting to broadcast...\n",
- print_mac(mac, hdr->addr1));
- iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
- return priv->hw_params.bcast_sta_id;
-
- default:
- IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
- return priv->hw_params.bcast_sta_id;
- }
-}
-
/*
* start REPLY_TX command process
*/
@@ -1829,7 +1667,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
hdr_len = ieee80211_get_hdrlen(fc);

/* Find (or create) index into station table for destination station */
- sta_id = iwl4965_get_sta_id(priv, hdr);
+ sta_id = iwl_get_sta_id(priv, hdr);
if (sta_id == IWL_INVALID_STATION) {
DECLARE_MAC_BUF(mac);

@@ -3585,7 +3423,7 @@ static void iwl4965_error_recovery(struct iwl_priv *priv)
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwl4965_commit_rxon(priv);

- iwl4965_rxon_add_station(priv, priv->bssid, 1);
+ iwl_rxon_add_station(priv, priv->bssid, 1);

spin_lock_irqsave(&priv->lock, flags);
priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
@@ -4911,8 +4749,8 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
/* clear out the station table */
iwlcore_clear_stations_table(priv);

- iwl4965_rxon_add_station(priv, iwl_bcast_addr, 0);
- iwl4965_rxon_add_station(priv, priv->bssid, 0);
+ iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
+ iwl_rxon_add_station(priv, priv->bssid, 0);
iwl4965_rate_scale_init(priv->hw, IWL_STA_ID);
iwl4965_send_beacon_cmd(priv);

@@ -5323,7 +5161,7 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
iwl4965_commit_rxon(priv);
iwl4965_activate_qos(priv, 1);
- iwl4965_rxon_add_station(priv, iwl_bcast_addr, 0);
+ iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
}
iwl4965_send_beacon_cmd(priv);

@@ -5412,7 +5250,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
else {
rc = iwl4965_commit_rxon(priv);
if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
- iwl4965_rxon_add_station(
+ iwl_rxon_add_station(
priv, priv->active_rxon.bssid_addr, 1);
}

--
1.5.3.6


2008-05-23 02:11:27

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: add ucode loaders for iwl5000

From: Ron Rindjunsky <[email protected]>

This patch adds ucode initialization handler and functions to load
ucode for iwl5000 NIC.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-5000.c | 134 +++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-dev.h | 8 ++
drivers/net/wireless/iwlwifi/iwl4965-base.c | 3 +
3 files changed, 145 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 00ad360..b6bdffc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -287,6 +287,139 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
return &priv->eeprom[address];
}

+/*
+ * ucode
+ */
+static int iwl5000_load_section(struct iwl_priv *priv,
+ struct fw_desc *image,
+ u32 dst_addr)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ dma_addr_t phy_addr = image->p_addr;
+ u32 byte_cnt = image->len;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ret = iwl_grab_nic_access(priv);
+ if (ret) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
+ }
+
+ iwl_write_direct32(priv,
+ FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);
+
+ iwl_write_direct32(priv,
+ FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr);
+
+ iwl_write_direct32(priv,
+ FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
+ phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);
+
+ /* FIME: write the MSB of the phy_addr in CTRL1
+ * iwl_write_direct32(priv,
+ IWL_FH_TFDIB_CTRL1_REG(IWL_FH_SRVC_CHNL),
+ ((phy_addr & MSB_MSK)
+ << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_count);
+ */
+ iwl_write_direct32(priv,
+ FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), byte_cnt);
+ iwl_write_direct32(priv,
+ FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL),
+ 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |
+ 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX |
+ FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID);
+
+ iwl_write_direct32(priv,
+ FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL |
+ FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
+
+ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return 0;
+}
+
+static int iwl5000_load_given_ucode(struct iwl_priv *priv,
+ struct fw_desc *inst_image,
+ struct fw_desc *data_image)
+{
+ int ret = 0;
+
+ ret = iwl5000_load_section(
+ priv, inst_image, RTC_INST_LOWER_BOUND);
+ if (ret)
+ return ret;
+
+ IWL_DEBUG_INFO("INST uCode section being loaded...\n");
+ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+ priv->ucode_write_complete, 5 * HZ);
+ if (ret == -ERESTARTSYS) {
+ IWL_ERROR("Could not load the INST uCode section due "
+ "to interrupt\n");
+ return ret;
+ }
+ if (!ret) {
+ IWL_ERROR("Could not load the INST uCode section\n");
+ return -ETIMEDOUT;
+ }
+
+ priv->ucode_write_complete = 0;
+
+ ret = iwl5000_load_section(
+ priv, data_image, RTC_DATA_LOWER_BOUND);
+ if (ret)
+ return ret;
+
+ IWL_DEBUG_INFO("DATA uCode section being loaded...\n");
+
+ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+ priv->ucode_write_complete, 5 * HZ);
+ if (ret == -ERESTARTSYS) {
+ IWL_ERROR("Could not load the INST uCode section due "
+ "to interrupt\n");
+ return ret;
+ } else if (!ret) {
+ IWL_ERROR("Could not load the DATA uCode section\n");
+ return -ETIMEDOUT;
+ } else
+ ret = 0;
+
+ priv->ucode_write_complete = 0;
+
+ return ret;
+}
+
+static int iwl5000_load_ucode(struct iwl_priv *priv)
+{
+ int ret = 0;
+
+ /* check whether init ucode should be loaded, or rather runtime ucode */
+ if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) {
+ IWL_DEBUG_INFO("Init ucode found. Loading init ucode...\n");
+ ret = iwl5000_load_given_ucode(priv,
+ &priv->ucode_init, &priv->ucode_init_data);
+ if (!ret) {
+ IWL_DEBUG_INFO("Init ucode load complete.\n");
+ priv->ucode_type = UCODE_INIT;
+ }
+ } else {
+ IWL_DEBUG_INFO("Init ucode not found, or already loaded. "
+ "Loading runtime ucode...\n");
+ ret = iwl5000_load_given_ucode(priv,
+ &priv->ucode_code, &priv->ucode_data);
+ if (!ret) {
+ IWL_DEBUG_INFO("Runtime ucode load complete.\n");
+ priv->ucode_type = UCODE_RT;
+ }
+ }
+
+ return ret;
+}
+
static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
{
if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) ||
@@ -488,6 +621,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
.disable_tx_fifo = iwl5000_disable_tx_fifo,
.rx_handler_setup = iwl5000_rx_handler_setup,
+ .load_ucode = iwl5000_load_ucode,
.apm_ops = {
.init = iwl5000_apm_init,
.config = iwl5000_nic_config,
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 533479e..b1ff0af 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -876,6 +876,12 @@ struct statistics_general_data {
u32 beacon_energy_c;
};

+enum ucode_type {
+ UCODE_NONE = 0,
+ UCODE_INIT,
+ UCODE_RT
+};
+
#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
/* Sensitivity calib data */
struct iwl_sensitivity_data {
@@ -1010,6 +1016,8 @@ struct iwl_priv {
struct fw_desc ucode_init; /* initialization inst */
struct fw_desc ucode_init_data; /* initialization data */
struct fw_desc ucode_boot; /* bootstrap inst */
+ enum ucode_type ucode_type;
+ u8 ucode_write_complete; /* the image write is complete */


struct iwl4965_rxon_time_cmd rxon_timing;
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 40616db..e06142d 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -2978,6 +2978,9 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
if (inta & CSR_INT_BIT_FH_TX) {
IWL_DEBUG_ISR("Tx interrupt\n");
handled |= CSR_INT_BIT_FH_TX;
+ /* FH finished to write, send event */
+ priv->ucode_write_complete = 1;
+ wake_up_interruptible(&priv->wait_command_queue);
}

if (inta & ~handled)
--
1.5.3.6


2008-05-23 02:11:46

by Zhu Yi

[permalink] [raw]
Subject: [PATCH] iwlwifi: remove unused variable form __iwl4965_down

From: Tomas Winkler <[email protected]>

This patch removes unused variable from __iwl4965_down.

Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl4965-base.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 038eea0..bf975cb 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -3349,12 +3349,9 @@ static void __iwl4965_down(struct iwl_priv *priv)
{
unsigned long flags;
int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
- struct ieee80211_conf *conf = NULL;

IWL_DEBUG_INFO(DRV_NAME " is going down\n");

- conf = ieee80211_get_hw_conf(priv->hw);
-
if (!exit_pending)
set_bit(STATUS_EXIT_PENDING, &priv->status);

--
1.5.3.6