2010-02-11 18:42:14

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 00/12] iwlwifi updates for 2.6.34

Included is a fix to a scan race introduced by the new internal scanning
code. We also now reset the card during the probe to support users of
kdump. Memory allocation is not done as often with GFP_ATOMIC to improve
success rate. Included are some fixes to help aggregation queues recover
after firmware reload as well as recovery after TX stalls. A new interface
is added to force reset of firmware.

These patches are also available from wireless-next-2.6 branch on
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git

Abhijeet Kolekar (1):
iwlwifi: cleanup return values

Reinette Chatre (2):
iwlwifi: fix scan race
iwlwifi: reset card during probe

Stanislaw Gruszka (1):
iwlwifi: use dma_alloc_coherent

Trieu 'Andrew' Nguyen (2):
iwlwifi: Adjusting PLCP error threshold for 1000 NIC
iwlwifi: Monitor and recover the aggregation TX flow failure

Wey-Yi Guy (6):
iwlwifi: clear all tx queues when firmware ready
iwlwifi: multiple force reset mode
iwlwifi: add debug function to reset/reload radio/firmware
iwlwifi: check for aggregation frame and queue
iwlwifi: remove unused op-code in PHY Calibration command
iwlwifi: clear all the stop_queue flag after load firmware

drivers/net/wireless/iwlwifi/iwl-1000.c | 4 +-
drivers/net/wireless/iwlwifi/iwl-3945.c | 8 +--
drivers/net/wireless/iwlwifi/iwl-4965.c | 7 ++
drivers/net/wireless/iwlwifi/iwl-5000.c | 7 ++
drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 15 +++++-
drivers/net/wireless/iwlwifi/iwl-agn.c | 22 +++++++-
drivers/net/wireless/iwlwifi/iwl-commands.h | 4 -
drivers/net/wireless/iwlwifi/iwl-core.c | 56 ++++++++++++++++---
drivers/net/wireless/iwlwifi/iwl-core.h | 8 +-
drivers/net/wireless/iwlwifi/iwl-debugfs.c | 28 +++++++++
drivers/net/wireless/iwlwifi/iwl-dev.h | 13 ++++-
drivers/net/wireless/iwlwifi/iwl-helpers.h | 7 +-
drivers/net/wireless/iwlwifi/iwl-rx.c | 80 ++++++++++++++++++++------
drivers/net/wireless/iwlwifi/iwl-scan.c | 37 ++++--------
drivers/net/wireless/iwlwifi/iwl-tx.c | 62 ++++++++++----------
drivers/net/wireless/iwlwifi/iwl3945-base.c | 39 ++++++-------
16 files changed, 273 insertions(+), 124 deletions(-)



2010-02-11 18:42:15

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 12/12] iwlwifi: Monitor and recover the aggregation TX flow failure

From: Trieu 'Andrew' Nguyen <[email protected]>

This change monitors the tx statistics to detect the drop in throughput.
When the throughput drops, the ratio of the actual_ack_count and the expected_
ack_count also drops. At the same time, the aggregated ba_timeout (the number
of ba timeout retries) also rises. If the actual_ack_count/expected_ack_count
ratio is 0 and the number of ba timeout retries rises to 16, no tx packets
(tcp, udp, or ping - icmp) can be delivered. The driver recovers from this
situation by reseting the uCode firmware. If the actual_ack_count/expected_
ack_count ratio drops below 50% (but not 0) and the aggregated ba_timeout
retries just exceed 5 (but not 16), then the driver can reset the radio to
bring the throughput up.

Signed-off-by: Trieu 'Andrew' Nguyen <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-agn.c | 14 +++++++++-
drivers/net/wireless/iwlwifi/iwl-dev.h | 3 ++
drivers/net/wireless/iwlwifi/iwl-rx.c | 46 ++++++++++++++++++++++++++++++++
3 files changed, 62 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 31b156d..4157c6c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2941,10 +2941,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
return ret;
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT(priv, "start Tx\n");
- return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
+ ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn);
+ if (ret == 0) {
+ priv->agg_tids_count++;
+ IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
+ priv->agg_tids_count);
+ }
+ return ret;
case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT(priv, "stop Tx\n");
ret = iwl_tx_agg_stop(priv, sta->addr, tid);
+ if ((ret == 0) && (priv->agg_tids_count > 0)) {
+ priv->agg_tids_count--;
+ IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
+ priv->agg_tids_count);
+ }
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return 0;
else
@@ -3364,6 +3375,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
priv->iw_mode = NL80211_IFTYPE_STATION;
priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
+ priv->agg_tids_count = 0;

/* Choose which receivers/antennas to use */
if (priv->cfg->ops->hcmd->set_rxon_chain)
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 71cf155..f81317d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1072,6 +1072,9 @@ struct iwl_priv {
/* storing the jiffies when the plcp error rate is received */
unsigned long plcp_jiffies;

+ /* reporting the number of tids has AGG on. 0 means no AGGREGATION */
+ u8 agg_tids_count;
+
/* force reset */
unsigned long last_force_reset_jiffies;

diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index aba8f4c..fed554a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -616,6 +616,11 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,

#define REG_RECALIB_PERIOD (60)

+/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
+#define ACK_CNT_RATIO (50)
+#define BA_TIMEOUT_CNT (5)
+#define BA_TIMEOUT_MAX (16)
+
#define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n"
void iwl_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
@@ -625,6 +630,9 @@ void iwl_rx_statistics(struct iwl_priv *priv,
int combined_plcp_delta;
unsigned int plcp_msec;
unsigned long plcp_received_jiffies;
+ int actual_ack_cnt_delta;
+ int expected_ack_cnt_delta;
+ int ba_timeout_delta;

IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
(int)sizeof(priv->statistics),
@@ -639,6 +647,44 @@ void iwl_rx_statistics(struct iwl_priv *priv,
#ifdef CONFIG_IWLWIFI_DEBUG
iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
#endif
+ actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
+ le32_to_cpu(priv->statistics.tx.actual_ack_cnt);
+ expected_ack_cnt_delta = le32_to_cpu(
+ pkt->u.stats.tx.expected_ack_cnt) -
+ le32_to_cpu(priv->statistics.tx.expected_ack_cnt);
+ ba_timeout_delta = le32_to_cpu(
+ pkt->u.stats.tx.agg.ba_timeout) -
+ le32_to_cpu(priv->statistics.tx.agg.ba_timeout);
+ if ((priv->agg_tids_count > 0) &&
+ (expected_ack_cnt_delta > 0) &&
+ (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) <
+ ACK_CNT_RATIO) &&
+ (ba_timeout_delta > BA_TIMEOUT_CNT)) {
+ IWL_DEBUG_RADIO(priv,
+ "actual_ack_cnt delta = %d, expected_ack_cnt = %d\n",
+ actual_ack_cnt_delta, expected_ack_cnt_delta);
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
+ priv->delta_statistics.tx.rx_detected_cnt);
+ IWL_DEBUG_RADIO(priv,
+ "ack_or_ba_timeout_collision delta = %d\n",
+ priv->delta_statistics.tx.ack_or_ba_timeout_collision);
+#endif
+ IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
+ ba_timeout_delta);
+ if ((actual_ack_cnt_delta == 0) &&
+ (ba_timeout_delta >=
+ BA_TIMEOUT_MAX)) {
+ IWL_DEBUG_RADIO(priv,
+ "call iwl_force_reset(IWL_FW_RESET)\n");
+ iwl_force_reset(priv, IWL_FW_RESET);
+ } else {
+ IWL_DEBUG_RADIO(priv,
+ "call iwl_force_reset(IWL_RF_RESET)\n");
+ iwl_force_reset(priv, IWL_RF_RESET);
+ }
+ }
/*
* check for plcp_err and trigger radio reset if it exceeds
* the plcp error threshold plcp_delta.
--
1.6.3.3


2010-02-11 18:42:13

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 03/12] iwlwifi: add debug function to reset/reload radio/firmware

From: Wey-Yi Guy <[email protected]>

Adding function to force reset radio or reload firmware from debugfs.

Signed-off-by: Wey-Yi Guy <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-debugfs.c | 28 ++++++++++++++++++++++++++++
1 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index d134301..78298be 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -2223,6 +2223,32 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
return count;
}

+static ssize_t iwl_dbgfs_force_reset_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_priv *priv = file->private_data;
+ char buf[8];
+ int buf_size;
+ int reset, ret;
+
+ 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", &reset) != 1)
+ return -EINVAL;
+ switch (reset) {
+ case IWL_RF_RESET:
+ case IWL_FW_RESET:
+ ret = iwl_force_reset(priv, reset);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret ? ret : count;
+}
+
DEBUGFS_READ_FILE_OPS(rx_statistics);
DEBUGFS_READ_FILE_OPS(tx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
@@ -2243,6 +2269,7 @@ DEBUGFS_READ_FILE_OPS(fh_reg);
DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
DEBUGFS_WRITE_FILE_OPS(internal_scan);
DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
+DEBUGFS_WRITE_FILE_OPS(force_reset);

/*
* Create the debugfs files and directories
@@ -2296,6 +2323,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR);
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
--
1.6.3.3


2010-02-11 18:42:14

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 04/12] iwlwifi: check for aggregation frame and queue

From: Wey-Yi Guy <[email protected]>

Error checking for aggregation frames should go into aggregation queue,
if aggregation queue not available, use legacy queue instead.
Also make sure the aggregation queue is available to activate,
if driver and mac80211 is out-of-sync, try to disable the queue and
sync-up with mac80211.

Signed-off-by: Wey-Yi Guy <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 15 ++++++++++++++-
drivers/net/wireless/iwlwifi/iwl-tx.c | 18 ++++++++++++------
2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 6aebced..8bf7c20 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -298,10 +298,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct iwl_lq_sta *lq_data, u8 tid,
struct ieee80211_sta *sta)
{
+ int ret;
+
if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
sta->addr, tid);
- ieee80211_start_tx_ba_session(sta, tid);
+ ret = ieee80211_start_tx_ba_session(sta, tid);
+ if (ret == -EAGAIN) {
+ /*
+ * driver and mac80211 is out of sync
+ * this might be cause by reloading firmware
+ * stop the tx ba session here
+ */
+ IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",
+ tid);
+ ret = ieee80211_stop_tx_ba_session(sta, tid,
+ WLAN_BACK_INITIATOR);
+ }
}
}

diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index d365d13..3788a3d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -806,8 +806,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
hdr->seq_ctrl |= cpu_to_le16(seq_number);
seq_number += 0x10;
/* aggregation is on for this <sta,tid> */
- if (info->flags & IEEE80211_TX_CTL_AMPDU)
+ if (info->flags & IEEE80211_TX_CTL_AMPDU &&
+ priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
+ }
}

txq = &priv->txq[txq_id];
@@ -1328,7 +1330,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
{
int tx_fifo_id, txq_id, sta_id, ssn = -1;
struct iwl_tid_data *tid_data;
- int ret, write_ptr, read_ptr;
+ int write_ptr, read_ptr;
unsigned long flags;

if (!ra) {
@@ -1380,13 +1382,17 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;

spin_lock_irqsave(&priv->lock, flags);
- ret = priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
+ /*
+ * the only reason this call can fail is queue number out of range,
+ * which can happen if uCode is reloaded and all the station
+ * information are lost. if it is outside the range, there is no need
+ * to deactivate the uCode queue, just return "success" to allow
+ * mac80211 to clean up it own data.
+ */
+ priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
tx_fifo_id);
spin_unlock_irqrestore(&priv->lock, flags);

- if (ret)
- return ret;
-
ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);

return 0;
--
1.6.3.3


2010-02-11 18:42:12

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 01/12] iwlwifi: clear all tx queues when firmware ready

From: Wey-Yi Guy <[email protected]>

Reset and clear all the tx queues when finished downloading runtime
uCode and ready to go into operation mode.

Signed-off-by: Wey-Yi Guy <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 2 ++
drivers/net/wireless/iwlwifi/iwl-5000.c | 2 ++
2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index aebe8c5..e479488 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -581,6 +581,8 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)

iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);

+ /* reset to 0 to enable all the queue first */
+ priv->txq_ctx_active_msk = 0;
/* 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];
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index f3d662c..a7fa1ad 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -648,6 +648,8 @@ int iwl5000_alive_notify(struct iwl_priv *priv)

iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);

+ /* reset to 0 to enable all the queue first */
+ priv->txq_ctx_active_msk = 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];
--
1.6.3.3


2010-02-11 18:42:16

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 11/12] iwlwifi: clear all the stop_queue flag after load firmware

From: Wey-Yi Guy <[email protected]>

All the queues are awake and ready to use after loading firmware,
for firmware reload case, if any queues was stopped before
reload, mac80211 will wake those queues after restart hardware, so make
sure all the flag used to keep track of the queue status are
reset correctly.

Signed-off-by: Wey-Yi Guy <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 5 +++++
drivers/net/wireless/iwlwifi/iwl-5000.c | 5 +++++
2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index e479488..17e91ad 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -581,6 +581,11 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)

iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);

+ /* make sure all queue are not stopped */
+ memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
+ for (i = 0; i < 4; i++)
+ atomic_set(&priv->queue_stop_count[i], 0);
+
/* reset to 0 to enable all the queue first */
priv->txq_ctx_active_msk = 0;
/* Map each Tx/cmd queue to its corresponding fifo */
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index a7fa1ad..94fc836 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -648,6 +648,11 @@ int iwl5000_alive_notify(struct iwl_priv *priv)

iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);

+ /* make sure all queue are not stopped */
+ memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
+ for (i = 0; i < 4; i++)
+ atomic_set(&priv->queue_stop_count[i], 0);
+
/* reset to 0 to enable all the queue first */
priv->txq_ctx_active_msk = 0;
/* map qos queues to fifos one-to-one */
--
1.6.3.3


2010-02-11 18:42:14

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 06/12] iwlwifi: cleanup return values

From: Abhijeet Kolekar <[email protected]>

Cleanup return values and removes unnecessary code.

Signed-off-by: Abhijeet Kolekar <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-core.h | 6 +++---
drivers/net/wireless/iwlwifi/iwl-rx.c | 11 +++--------
drivers/net/wireless/iwlwifi/iwl-tx.c | 21 +++++++--------------
drivers/net/wireless/iwlwifi/iwl3945-base.c | 16 ++++------------
4 files changed, 17 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index df55879..530fae8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -414,13 +414,13 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
void iwl_cmd_queue_free(struct iwl_priv *priv);
int iwl_rx_queue_alloc(struct iwl_priv *priv);
void iwl_rx_handle(struct iwl_priv *priv);
-int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
+void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
struct iwl_rx_queue *q);
void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
void iwl_rx_replenish(struct iwl_priv *priv);
void iwl_rx_replenish_now(struct iwl_priv *priv);
int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-int iwl_rx_queue_restock(struct iwl_priv *priv);
+void 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, gfp_t priority);
void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
@@ -450,7 +450,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
int iwl_hw_tx_queue_init(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
-int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
int slots_num, u32 txq_id);
void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 909d9c9..428c9d6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -123,12 +123,11 @@ EXPORT_SYMBOL(iwl_rx_queue_space);
/**
* iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
*/
-int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
+void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
{
unsigned long flags;
u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;
u32 reg;
- int ret = 0;

spin_lock_irqsave(&q->lock, flags);

@@ -161,7 +160,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)

exit_unlock:
spin_unlock_irqrestore(&q->lock, flags);
- return ret;
}
EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr);
/**
@@ -184,14 +182,13 @@ static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
* also updates the memory address in the firmware to reference the new
* target buffer.
*/
-int iwl_rx_queue_restock(struct iwl_priv *priv)
+void iwl_rx_queue_restock(struct iwl_priv *priv)
{
struct iwl_rx_queue *rxq = &priv->rxq;
struct list_head *element;
struct iwl_rx_mem_buffer *rxb;
unsigned long flags;
int write;
- int ret = 0;

spin_lock_irqsave(&rxq->lock, flags);
write = rxq->write & ~0x7;
@@ -220,10 +217,8 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags);
- ret = iwl_rx_queue_update_write_ptr(priv, rxq);
+ iwl_rx_queue_update_write_ptr(priv, rxq);
}
-
- return ret;
}
EXPORT_SYMBOL(iwl_rx_queue_restock);

diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 3788a3d..2199b1b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -80,14 +80,13 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv,
/**
* 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)
+void 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;
+ return;

/* if we're trying to save power */
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
@@ -101,7 +100,7 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
txq_id, reg);
iwl_set_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- return ret;
+ return;
}

iwl_write_direct32(priv, HBUS_TARG_WRPTR,
@@ -114,8 +113,6 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
txq->q.write_ptr | (txq_id << 8));

txq->need_update = 0;
-
- return ret;
}
EXPORT_SYMBOL(iwl_txq_update_write_ptr);

@@ -731,7 +728,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
u8 tid = 0;
u8 *qc = NULL;
unsigned long flags;
- int ret;

spin_lock_irqsave(&priv->lock, flags);
if (iwl_is_rfkill(priv)) {
@@ -951,7 +947,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)

/* 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);
+ iwl_txq_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags);

/*
@@ -965,9 +961,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
if (sta_priv && sta_priv->client)
atomic_inc(&sta_priv->pending_frames);

- 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);
@@ -1006,7 +999,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
struct iwl_cmd_meta *out_meta;
dma_addr_t phys_addr;
unsigned long flags;
- int len, ret;
+ int len;
u32 idx;
u16 fix_size;

@@ -1103,10 +1096,10 @@ int iwl_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 = iwl_txq_update_write_ptr(priv, txq);
+ iwl_txq_update_write_ptr(priv, txq);

spin_unlock_irqrestore(&priv->hcmd_lock, flags);
- return ret ? ret : idx;
+ return idx;
}

static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index eac2b9a..f6e8f45 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -478,7 +478,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
u8 wait_write_ptr = 0;
u8 *qc = NULL;
unsigned long flags;
- int rc;

spin_lock_irqsave(&priv->lock, flags);
if (iwl_is_rfkill(priv)) {
@@ -663,12 +662,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)

/* 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);
+ 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) {
@@ -1063,13 +1059,13 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
* also updates the memory address in the firmware to reference the new
* target buffer.
*/
-static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
+static void iwl3945_rx_queue_restock(struct iwl_priv *priv)
{
struct iwl_rx_queue *rxq = &priv->rxq;
struct list_head *element;
struct iwl_rx_mem_buffer *rxb;
unsigned long flags;
- int write, rc;
+ int write;

spin_lock_irqsave(&rxq->lock, flags);
write = rxq->write & ~0x7;
@@ -1099,12 +1095,8 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags);
- rc = iwl_rx_queue_update_write_ptr(priv, rxq);
- if (rc)
- return rc;
+ iwl_rx_queue_update_write_ptr(priv, rxq);
}
-
- return 0;
}

/**
--
1.6.3.3


2010-02-11 18:42:13

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 02/12] iwlwifi: multiple force reset mode

From: Wey-Yi Guy <[email protected]>

Provide the function to perform different type of uCode reset/reload operation.
When uCode detect error and can not fix itself, this iwl_force_reset()
function allow driver to perform the necessary reset/reload functions and help
to bring uCode back to normal operation state.

Currently only 2 type of force reset are available:
- reset radio
- reload firmware

Signed-off-by: Wey-Yi Guy <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-core.c | 44 +++++++++++++++++++++++++++++-
drivers/net/wireless/iwlwifi/iwl-core.h | 2 +-
drivers/net/wireless/iwlwifi/iwl-dev.h | 9 +++++-
drivers/net/wireless/iwlwifi/iwl-rx.c | 2 +-
drivers/net/wireless/iwlwifi/iwl-scan.c | 10 -------
5 files changed, 52 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index d390eef..500ced4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -3334,7 +3334,7 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
}
EXPORT_SYMBOL(iwl_dump_fh);

-void iwl_force_rf_reset(struct iwl_priv *priv)
+static void iwl_force_rf_reset(struct iwl_priv *priv)
{
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -3356,7 +3356,47 @@ void iwl_force_rf_reset(struct iwl_priv *priv)
iwl_internal_short_hw_scan(priv);
return;
}
-EXPORT_SYMBOL(iwl_force_rf_reset);
+
+#define IWL_DELAY_NEXT_FORCE_RESET (HZ*3)
+
+int iwl_force_reset(struct iwl_priv *priv, int mode)
+{
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return -EINVAL;
+
+ if (priv->last_force_reset_jiffies &&
+ time_after(priv->last_force_reset_jiffies +
+ IWL_DELAY_NEXT_FORCE_RESET, jiffies)) {
+ IWL_DEBUG_INFO(priv, "force reset rejected\n");
+ return -EAGAIN;
+ }
+
+ IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
+
+ switch (mode) {
+ case IWL_RF_RESET:
+ iwl_force_rf_reset(priv);
+ break;
+ case IWL_FW_RESET:
+ IWL_ERR(priv, "On demand firmware reload\n");
+ /* Set the FW error flag -- cleared on iwl_down */
+ set_bit(STATUS_FW_ERROR, &priv->status);
+ wake_up_interruptible(&priv->wait_command_queue);
+ /*
+ * Keep the restart process from trying to send host
+ * commands by clearing the INIT status bit
+ */
+ clear_bit(STATUS_READY, &priv->status);
+ queue_work(priv->workqueue, &priv->restart);
+ break;
+ default:
+ IWL_DEBUG_INFO(priv, "invalid reset request.\n");
+ return -EINVAL;
+ }
+ priv->last_force_reset_jiffies = jiffies;
+
+ return 0;
+}

#ifdef CONFIG_PM

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 8f0c564..df55879 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -501,7 +501,7 @@ int iwl_scan_cancel(struct iwl_priv *priv);
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
int iwl_internal_short_hw_scan(struct iwl_priv *priv);
-void iwl_force_rf_reset(struct iwl_priv *priv);
+int iwl_force_reset(struct iwl_priv *priv, int mode);
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
const u8 *ie, int ie_len, int left);
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 55dc5a8..9f1d302 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1035,6 +1035,11 @@ struct iwl_event_log {
#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)

+enum iwl_reset {
+ IWL_RF_RESET = 0,
+ IWL_FW_RESET,
+};
+
struct iwl_priv {

/* ieee device used by generic ieee processing code */
@@ -1066,6 +1071,9 @@ struct iwl_priv {
/* storing the jiffies when the plcp error rate is received */
unsigned long plcp_jiffies;

+ /* force reset */
+ unsigned long last_force_reset_jiffies;
+
/* we allocate array of iwl4965_channel_info for NIC's valid channels.
* Access via channel # using indirect index array */
struct iwl_channel_info *channel_info; /* channel info array */
@@ -1087,7 +1095,6 @@ struct iwl_priv {
unsigned long scan_start;
unsigned long scan_pass_start;
unsigned long scan_start_tsf;
- unsigned long last_internal_scan_jiffies;
void *scan;
int scan_bands;
struct cfg80211_scan_request *scan_request;
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 5df6638..909d9c9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -689,7 +689,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
* Reset the RF radio due to the high plcp
* error rate
*/
- iwl_force_rf_reset(priv);
+ iwl_force_reset(priv, IWL_RF_RESET);
}
}

diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index f786a40..5014774 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -250,8 +250,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,

if (!priv->is_internal_short_scan)
priv->next_scan_jiffies = 0;
- else
- priv->last_internal_scan_jiffies = jiffies;

IWL_DEBUG_INFO(priv, "Setting scan to off\n");

@@ -551,8 +549,6 @@ EXPORT_SYMBOL(iwl_mac_hw_scan);
* internal short scan, this function should only been called while associated.
* It will reset and tune the radio to prevent possible RF related problem
*/
-#define IWL_DELAY_NEXT_INTERNAL_SCAN (HZ*1)
-
int iwl_internal_short_hw_scan(struct iwl_priv *priv)
{
int ret = 0;
@@ -572,12 +568,6 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv)
ret = -EAGAIN;
goto out;
}
- if (priv->last_internal_scan_jiffies &&
- time_after(priv->last_internal_scan_jiffies +
- IWL_DELAY_NEXT_INTERNAL_SCAN, jiffies)) {
- IWL_DEBUG_SCAN(priv, "internal scan rejected\n");
- goto out;
- }

priv->scan_bands = 0;
if (priv->band == IEEE80211_BAND_5GHZ)
--
1.6.3.3


2010-02-11 20:17:51

by Cahill, Ben M

[permalink] [raw]
Subject: RE: [ipw3945-devel] [PATCH 05/12] iwlwifi: remove unused op-code in PHY Calibration command

NACK. Keep them around; we may use in the future.

-- Ben --

>-----Original Message-----
>From: Reinette Chatre [mailto:[email protected]]
>Sent: Thursday, February 11, 2010 1:42 PM
>To: [email protected]
>Cc: Chatre, Reinette; [email protected];
>[email protected]
>Subject: [ipw3945-devel] [PATCH 05/12] iwlwifi: remove unused
>op-code in PHY Calibration command
>
>From: Wey-Yi Guy <[email protected]>
>
>Number of calibration op-code are not used by driver, remove those from
>iwl-commands.h
>
>Signed-off-by: Wey-Yi Guy <[email protected]>
>Signed-off-by: Reinette Chatre <[email protected]>
>---
> drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ----
> 1 files changed, 0 insertions(+), 4 deletions(-)
>
>diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h
>b/drivers/net/wireless/iwlwifi/iwl-commands.h
>index c2f31eb..ab3c77b 100644
>--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
>+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
>@@ -3470,11 +3470,7 @@ enum {
> IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
> IWL_PHY_CALIBRATE_DC_CMD = 8,
> IWL_PHY_CALIBRATE_LO_CMD = 9,
>- IWL_PHY_CALIBRATE_RX_BB_CMD = 10,
> IWL_PHY_CALIBRATE_TX_IQ_CMD = 11,
>- IWL_PHY_CALIBRATE_RX_IQ_CMD = 12,
>- IWL_PHY_CALIBRATION_NOISE_CMD = 13,
>- IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
> IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
> IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
> IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
>--
>1.6.3.3
>
>
>---------------------------------------------------------------
>---------------
>SOLARIS 10 is the OS for Data Centers - provides features such
>as DTrace,
>Predictive Self Healing and Award Winning ZFS. Get Solaris 10 NOW
>http://p.sf.net/sfu/solaris-dev2dev
>_______________________________________________
>Ipw3945-devel mailing list
>[email protected]
>https://lists.sourceforge.net/lists/listinfo/ipw3945-devel
>

2010-02-12 14:00:08

by Andrew Lutomirski

[permalink] [raw]
Subject: Re: [PATCH 12/12] iwlwifi: Monitor and recover the aggregation TX flow failure

Reinette Chatre wrote:
> From: Trieu 'Andrew' Nguyen <[email protected]>
>
> This change monitors the tx statistics to detect the drop in throughput.
> When the throughput drops, the ratio of the actual_ack_count and the expected_
> ack_count also drops. At the same time, the aggregated ba_timeout (the number
> of ba timeout retries) also rises. If the actual_ack_count/expected_ack_count
> ratio is 0 and the number of ba timeout retries rises to 16, no tx packets
> (tcp, udp, or ping - icmp) can be delivered. The driver recovers from this
> situation by reseting the uCode firmware. If the actual_ack_count/expected_
> ack_count ratio drops below 50% (but not 0) and the aggregated ba_timeout
> retries just exceed 5 (but not 16), then the driver can reset the radio to
> bring the throughput up.

Any chance this fixes big 2120? Maybe I'm too optimistic, but I'll try
to test it this afternoon.

http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2120

--Andy

>
> Signed-off-by: Trieu 'Andrew' Nguyen <[email protected]>
> Signed-off-by: Reinette Chatre <[email protected]>
> ---
> drivers/net/wireless/iwlwifi/iwl-agn.c | 14 +++++++++-
> drivers/net/wireless/iwlwifi/iwl-dev.h | 3 ++
> drivers/net/wireless/iwlwifi/iwl-rx.c | 46 ++++++++++++++++++++++++++++++++
> 3 files changed, 62 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
> index 31b156d..4157c6c 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-agn.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
> @@ -2941,10 +2941,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
> return ret;
> case IEEE80211_AMPDU_TX_START:
> IWL_DEBUG_HT(priv, "start Tx\n");
> - return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
> + ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn);
> + if (ret == 0) {
> + priv->agg_tids_count++;
> + IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
> + priv->agg_tids_count);
> + }
> + return ret;
> case IEEE80211_AMPDU_TX_STOP:
> IWL_DEBUG_HT(priv, "stop Tx\n");
> ret = iwl_tx_agg_stop(priv, sta->addr, tid);
> + if ((ret == 0) && (priv->agg_tids_count > 0)) {
> + priv->agg_tids_count--;
> + IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
> + priv->agg_tids_count);
> + }
> if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> return 0;
> else
> @@ -3364,6 +3375,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
> priv->iw_mode = NL80211_IFTYPE_STATION;
> priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
> priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
> + priv->agg_tids_count = 0;
>
> /* Choose which receivers/antennas to use */
> if (priv->cfg->ops->hcmd->set_rxon_chain)
> diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
> index 71cf155..f81317d 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-dev.h
> +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
> @@ -1072,6 +1072,9 @@ struct iwl_priv {
> /* storing the jiffies when the plcp error rate is received */
> unsigned long plcp_jiffies;
>
> + /* reporting the number of tids has AGG on. 0 means no AGGREGATION */
> + u8 agg_tids_count;
> +
> /* force reset */
> unsigned long last_force_reset_jiffies;
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
> index aba8f4c..fed554a 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-rx.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
> @@ -616,6 +616,11 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
>
> #define REG_RECALIB_PERIOD (60)
>
> +/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
> +#define ACK_CNT_RATIO (50)
> +#define BA_TIMEOUT_CNT (5)
> +#define BA_TIMEOUT_MAX (16)
> +
> #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n"
> void iwl_rx_statistics(struct iwl_priv *priv,
> struct iwl_rx_mem_buffer *rxb)
> @@ -625,6 +630,9 @@ void iwl_rx_statistics(struct iwl_priv *priv,
> int combined_plcp_delta;
> unsigned int plcp_msec;
> unsigned long plcp_received_jiffies;
> + int actual_ack_cnt_delta;
> + int expected_ack_cnt_delta;
> + int ba_timeout_delta;
>
> IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
> (int)sizeof(priv->statistics),
> @@ -639,6 +647,44 @@ void iwl_rx_statistics(struct iwl_priv *priv,
> #ifdef CONFIG_IWLWIFI_DEBUG
> iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
> #endif
> + actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
> + le32_to_cpu(priv->statistics.tx.actual_ack_cnt);
> + expected_ack_cnt_delta = le32_to_cpu(
> + pkt->u.stats.tx.expected_ack_cnt) -
> + le32_to_cpu(priv->statistics.tx.expected_ack_cnt);
> + ba_timeout_delta = le32_to_cpu(
> + pkt->u.stats.tx.agg.ba_timeout) -
> + le32_to_cpu(priv->statistics.tx.agg.ba_timeout);
> + if ((priv->agg_tids_count > 0) &&
> + (expected_ack_cnt_delta > 0) &&
> + (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) <
> + ACK_CNT_RATIO) &&
> + (ba_timeout_delta > BA_TIMEOUT_CNT)) {
> + IWL_DEBUG_RADIO(priv,
> + "actual_ack_cnt delta = %d, expected_ack_cnt = %d\n",
> + actual_ack_cnt_delta, expected_ack_cnt_delta);
> +
> +#ifdef CONFIG_IWLWIFI_DEBUG
> + IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
> + priv->delta_statistics.tx.rx_detected_cnt);
> + IWL_DEBUG_RADIO(priv,
> + "ack_or_ba_timeout_collision delta = %d\n",
> + priv->delta_statistics.tx.ack_or_ba_timeout_collision);
> +#endif
> + IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
> + ba_timeout_delta);
> + if ((actual_ack_cnt_delta == 0) &&
> + (ba_timeout_delta >=
> + BA_TIMEOUT_MAX)) {
> + IWL_DEBUG_RADIO(priv,
> + "call iwl_force_reset(IWL_FW_RESET)\n");
> + iwl_force_reset(priv, IWL_FW_RESET);
> + } else {
> + IWL_DEBUG_RADIO(priv,
> + "call iwl_force_reset(IWL_RF_RESET)\n");
> + iwl_force_reset(priv, IWL_RF_RESET);
> + }
> + }
> /*
> * check for plcp_err and trigger radio reset if it exceeds
> * the plcp error threshold plcp_delta.


2010-02-11 18:42:14

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 07/12] iwlwifi: fix scan race

From: Reinette Chatre <[email protected]>

There is a problem if an "internal short scan" is in progress when a
mac80211 requested scan arrives. If this new scan request arrives within
the "next_scan_jiffies" period then driver will immediately return success
and complete the scan. The problem here is that the scan has not been
fully initialized at this time (is_internal_short_scan is still set to true
because of the currently running scan), which results in the scan
completion never to be sent to mac80211. At this time also, evan though the
internal short scan is still running the state (is_internal_short_scan)
will be set to false, so when the internal scan does complete then mac80211
will receive a scan completion.

Fix this by checking right away if a scan is in progress when a scan
request arrives from mac80211.

Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-scan.c | 27 ++++++++++++---------------
1 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 5014774..dd9ff2e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -469,21 +469,6 @@ EXPORT_SYMBOL(iwl_init_scan_params);

static int iwl_scan_initiate(struct iwl_priv *priv)
{
- if (!iwl_is_ready_rf(priv)) {
- IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n");
- return -EIO;
- }
-
- if (test_bit(STATUS_SCANNING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
- return -EAGAIN;
- }
-
- if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
- return -EAGAIN;
- }
-
IWL_DEBUG_INFO(priv, "Starting scan...\n");
set_bit(STATUS_SCANNING, &priv->status);
priv->is_internal_short_scan = false;
@@ -515,6 +500,18 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
goto out_unlock;
}

+ if (test_bit(STATUS_SCANNING, &priv->status)) {
+ IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
+ ret = -EAGAIN;
+ goto out_unlock;
+ }
+
+ if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+ IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
+ ret = -EAGAIN;
+ goto out_unlock;
+ }
+
/* We don't schedule scan within next_scan_jiffies period.
* Avoid scanning during possible EAPOL exchange, return
* success immediately.
--
1.6.3.3


2010-02-11 18:42:15

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 10/12] iwlwifi: use dma_alloc_coherent

From: Stanislaw Gruszka <[email protected]>

Change pci_alloc_consistent() to dma_alloc_coherent() so we can use
GFP_KERNEL flag.

Signed-off-by: Stanislaw Gruszka <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-3945.c | 8 +++-----
drivers/net/wireless/iwlwifi/iwl-core.c | 12 ++++++------
drivers/net/wireless/iwlwifi/iwl-helpers.h | 7 ++++---
drivers/net/wireless/iwlwifi/iwl-rx.c | 21 +++++++++++----------
drivers/net/wireless/iwlwifi/iwl-tx.c | 23 ++++++++++++-----------
drivers/net/wireless/iwlwifi/iwl3945-base.c | 16 ++++++++--------
6 files changed, 44 insertions(+), 43 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 57194bb..5913418 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2470,11 +2470,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
memset((void *)&priv->hw_params, 0,
sizeof(struct iwl_hw_params));

- priv->shared_virt =
- pci_alloc_consistent(priv->pci_dev,
- sizeof(struct iwl3945_shared),
- &priv->shared_phys);
-
+ priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev,
+ sizeof(struct iwl3945_shared),
+ &priv->shared_phys, GFP_KERNEL);
if (!priv->shared_virt) {
IWL_ERR(priv, "failed to allocate pci memory\n");
mutex_unlock(&priv->mutex);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 500ced4..bd56827 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1670,9 +1670,9 @@ EXPORT_SYMBOL(iwl_set_tx_power);
void iwl_free_isr_ict(struct iwl_priv *priv)
{
if (priv->ict_tbl_vir) {
- pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) +
- PAGE_SIZE, priv->ict_tbl_vir,
- priv->ict_tbl_dma);
+ dma_free_coherent(&priv->pci_dev->dev,
+ (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+ priv->ict_tbl_vir, priv->ict_tbl_dma);
priv->ict_tbl_vir = NULL;
}
}
@@ -1688,9 +1688,9 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv)
if (priv->cfg->use_isr_legacy)
return 0;
/* allocate shrared data table */
- priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) *
- ICT_COUNT) + PAGE_SIZE,
- &priv->ict_tbl_dma);
+ priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev,
+ (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+ &priv->ict_tbl_dma, GFP_KERNEL);
if (!priv->ict_tbl_vir)
return -ENOMEM;

diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 45af5bb..51a67fb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -80,8 +80,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
struct fw_desc *desc)
{
if (desc->v_addr)
- pci_free_consistent(pci_dev, desc->len,
- desc->v_addr, desc->p_addr);
+ dma_free_coherent(&pci_dev->dev, desc->len,
+ desc->v_addr, desc->p_addr);
desc->v_addr = NULL;
desc->len = 0;
}
@@ -89,7 +89,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev,
struct fw_desc *desc)
{
- desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr);
+ desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
+ &desc->p_addr, GFP_KERNEL);
return (desc->v_addr != NULL) ? 0 : -ENOMEM;
}

diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 428c9d6..aba8f4c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -345,10 +345,10 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
}
}

- pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
- rxq->dma_addr);
- pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
- rxq->rb_stts, rxq->rb_stts_dma);
+ dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+ rxq->dma_addr);
+ dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
+ rxq->rb_stts, rxq->rb_stts_dma);
rxq->bd = NULL;
rxq->rb_stts = NULL;
}
@@ -357,7 +357,7 @@ EXPORT_SYMBOL(iwl_rx_queue_free);
int iwl_rx_queue_alloc(struct iwl_priv *priv)
{
struct iwl_rx_queue *rxq = &priv->rxq;
- struct pci_dev *dev = priv->pci_dev;
+ struct device *dev = &priv->pci_dev->dev;
int i;

spin_lock_init(&rxq->lock);
@@ -365,12 +365,13 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
INIT_LIST_HEAD(&rxq->rx_used);

/* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
- rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
+ rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr,
+ GFP_KERNEL);
if (!rxq->bd)
goto err_bd;

- rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status),
- &rxq->rb_stts_dma);
+ rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),
+ &rxq->rb_stts_dma, GFP_KERNEL);
if (!rxq->rb_stts)
goto err_rb;

@@ -387,8 +388,8 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
return 0;

err_rb:
- pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
- rxq->dma_addr);
+ dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+ rxq->dma_addr);
err_bd:
return -ENOMEM;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 2199b1b..d8c11f9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -60,7 +60,8 @@ static const u16 default_tid_to_tx_fifo[] = {
static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv,
struct iwl_dma_ptr *ptr, size_t size)
{
- ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma);
+ ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
+ GFP_KERNEL);
if (!ptr->addr)
return -ENOMEM;
ptr->size = size;
@@ -73,7 +74,7 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv,
if (unlikely(!ptr->addr))
return;

- pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma);
+ dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
memset(ptr, 0, sizeof(*ptr));
}

@@ -129,7 +130,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
{
struct iwl_tx_queue *txq = &priv->txq[txq_id];
struct iwl_queue *q = &txq->q;
- struct pci_dev *dev = priv->pci_dev;
+ struct device *dev = &priv->pci_dev->dev;
int i;

if (q->n_bd == 0)
@@ -146,8 +147,8 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)

/* De-alloc circular buffer of TFDs */
if (txq->q.n_bd)
- pci_free_consistent(dev, priv->hw_params.tfd_size *
- txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+ dma_free_coherent(dev, priv->hw_params.tfd_size *
+ txq->q.n_bd, txq->tfds, txq->q.dma_addr);

/* De-alloc array of per-TFD driver data */
kfree(txq->txb);
@@ -176,7 +177,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
{
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
struct iwl_queue *q = &txq->q;
- struct pci_dev *dev = priv->pci_dev;
+ struct device *dev = &priv->pci_dev->dev;
int i;

if (q->n_bd == 0)
@@ -188,8 +189,8 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)

/* De-alloc circular buffer of TFDs */
if (txq->q.n_bd)
- pci_free_consistent(dev, priv->hw_params.tfd_size *
- txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+ dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd,
+ txq->tfds, txq->q.dma_addr);

/* deallocate arrays */
kfree(txq->cmd);
@@ -280,7 +281,7 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
static int iwl_tx_queue_alloc(struct iwl_priv *priv,
struct iwl_tx_queue *txq, u32 id)
{
- struct pci_dev *dev = priv->pci_dev;
+ struct device *dev = &priv->pci_dev->dev;
size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;

/* Driver private data, only for Tx (not command) queues,
@@ -299,8 +300,8 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,

/* Circular buffer of transmit frame descriptors (TFDs),
* shared with device */
- txq->tfds = pci_alloc_consistent(dev, tfd_sz, &txq->q.dma_addr);
-
+ txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
+ GFP_KERNEL);
if (!txq->tfds) {
IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
goto error;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 7af8ab8..3df488a 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -352,10 +352,10 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
static void iwl3945_unset_hw_params(struct iwl_priv *priv)
{
if (priv->shared_virt)
- pci_free_consistent(priv->pci_dev,
- sizeof(struct iwl3945_shared),
- priv->shared_virt,
- priv->shared_phys);
+ dma_free_coherent(&priv->pci_dev->dev,
+ sizeof(struct iwl3945_shared),
+ priv->shared_virt,
+ priv->shared_phys);
}

static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
@@ -1241,10 +1241,10 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx
}
}

- pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
- rxq->dma_addr);
- pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
- rxq->rb_stts, rxq->rb_stts_dma);
+ dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+ rxq->dma_addr);
+ dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
+ rxq->rb_stts, rxq->rb_stts_dma);
rxq->bd = NULL;
rxq->rb_stts = NULL;
}
--
1.6.3.3


2010-02-11 18:42:15

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 08/12] iwlwifi: reset card during probe

From: Reinette Chatre <[email protected]>

To ensure that card is in a sane state during probe we add a reset call.
This change was prompted by users of kdump who was not able to bring up the
wireless driver in the kdump kernel. The problem here was that the primary
kernel, which is not running at the time, left the wireless card up and
running. When the kdump kernel starts it is thus possible to immediately
receive interrupts from firmware after registering interrupt, but without
being ready to deal with interrupts from firmware yet.

Reported-by: Stanislaw Gruszka <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-agn.c | 8 ++++++++
drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 +++++++
2 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index c1eff4c..31b156d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3540,6 +3540,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
spin_lock_init(&priv->reg_lock);
spin_lock_init(&priv->lock);
+
+ /*
+ * stop and reset the on-board processor just in case it is in a
+ * strange state ... like being left stranded by a primary kernel
+ * and this is now the kdump kernel trying to start up
+ */
+ iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
iwl_hw_detect(priv);
IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n",
priv->cfg->name, priv->hw_rev);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index f6e8f45..7af8ab8 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -4039,6 +4039,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
spin_lock_init(&priv->reg_lock);
spin_lock_init(&priv->lock);

+ /*
+ * stop and reset the on-board processor just in case it is in a
+ * strange state ... like being left stranded by a primary kernel
+ * and this is now the kdump kernel trying to start up
+ */
+ iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
/***********************
* 4. Read EEPROM
* ********************/
--
1.6.3.3


2010-02-11 18:42:15

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 09/12] iwlwifi: Adjusting PLCP error threshold for 1000 NIC

From: Trieu 'Andrew' Nguyen <[email protected]>

While testing the station with the NIC 1000 family, it is found that
the plcp error can easily exceed 50 value in 100mSecs. This creates
unneccessary radio reset/tuning. This patch raises the PLCP error
threshold of the NIC 1000 from 50 to 200 error count.

Signed-off-by: Trieu 'Andrew' Nguyen <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-1000.c | 4 ++--
drivers/net/wireless/iwlwifi/iwl-dev.h | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 694ceef..3bf2e6e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -246,7 +246,7 @@ struct iwl_cfg iwl1000_bgn_cfg = {
.use_rts_for_ht = true, /* use rts/cts protection */
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
.chain_noise_scale = 1000,
};

@@ -274,7 +274,7 @@ struct iwl_cfg iwl1000_bg_cfg = {
.led_compensation = 51,
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
.chain_noise_scale = 1000,
};

diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 9f1d302..71cf155 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1033,6 +1033,7 @@ struct iwl_event_log {
#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0)
#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
+#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200)
#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)

enum iwl_reset {
--
1.6.3.3


2010-02-11 18:42:13

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 05/12] iwlwifi: remove unused op-code in PHY Calibration command

From: Wey-Yi Guy <[email protected]>

Number of calibration op-code are not used by driver, remove those from
iwl-commands.h

Signed-off-by: Wey-Yi Guy <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index c2f31eb..ab3c77b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -3470,11 +3470,7 @@ enum {
IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
IWL_PHY_CALIBRATE_DC_CMD = 8,
IWL_PHY_CALIBRATE_LO_CMD = 9,
- IWL_PHY_CALIBRATE_RX_BB_CMD = 10,
IWL_PHY_CALIBRATE_TX_IQ_CMD = 11,
- IWL_PHY_CALIBRATE_RX_IQ_CMD = 12,
- IWL_PHY_CALIBRATION_NOISE_CMD = 13,
- IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
--
1.6.3.3


2010-02-11 21:23:35

by Cahill, Ben M

[permalink] [raw]
Subject: RE: [ipw3945-devel] [PATCH 05/12] iwlwifi: remove unused op-code in PHY Calibration command

Okay, ACK.

-- Ben --

>-----Original Message-----
>From: Guy, Wey-Yi W
>Sent: Thursday, February 11, 2010 3:23 PM
>To: Cahill, Ben M
>Cc: Chatre, Reinette; [email protected];
>[email protected]; [email protected]
>Subject: RE: [ipw3945-devel] [PATCH 05/12] iwlwifi: remove
>unused op-code in PHY Calibration command
>
>Hi Ben,
>
>this is per Giora's request to remove unused calibration command. so we
>will not alarm external to play with those commands.
>
>we can add those back in if we are going to use it.
>
>Wey
>
>On Thu, 2010-02-11 at 12:17 -0800, Cahill, Ben M wrote:
>> NACK. Keep them around; we may use in the future.
>>
>> -- Ben --
>>
>> >-----Original Message-----
>> >From: Reinette Chatre [mailto:[email protected]]
>> >Sent: Thursday, February 11, 2010 1:42 PM
>> >To: [email protected]
>> >Cc: Chatre, Reinette; [email protected];
>> >[email protected]
>> >Subject: [ipw3945-devel] [PATCH 05/12] iwlwifi: remove unused
>> >op-code in PHY Calibration command
>> >
>> >From: Wey-Yi Guy <[email protected]>
>> >
>> >Number of calibration op-code are not used by driver,
>remove those from
>> >iwl-commands.h
>> >
>> >Signed-off-by: Wey-Yi Guy <[email protected]>
>> >Signed-off-by: Reinette Chatre <[email protected]>
>> >---
>> > drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ----
>> > 1 files changed, 0 insertions(+), 4 deletions(-)
>> >
>> >diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h
>> >b/drivers/net/wireless/iwlwifi/iwl-commands.h
>> >index c2f31eb..ab3c77b 100644
>> >--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
>> >+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
>> >@@ -3470,11 +3470,7 @@ enum {
>> > IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
>> > IWL_PHY_CALIBRATE_DC_CMD = 8,
>> > IWL_PHY_CALIBRATE_LO_CMD = 9,
>> >- IWL_PHY_CALIBRATE_RX_BB_CMD = 10,
>> > IWL_PHY_CALIBRATE_TX_IQ_CMD = 11,
>> >- IWL_PHY_CALIBRATE_RX_IQ_CMD = 12,
>> >- IWL_PHY_CALIBRATION_NOISE_CMD = 13,
>> >- IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
>> > IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
>> > IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
>> > IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
>> >--
>> >1.6.3.3
>> >
>> >
>> >---------------------------------------------------------------
>> >---------------
>> >SOLARIS 10 is the OS for Data Centers - provides features such
>> >as DTrace,
>> >Predictive Self Healing and Award Winning ZFS. Get Solaris 10 NOW
>> >http://p.sf.net/sfu/solaris-dev2dev
>> >_______________________________________________
>> >Ipw3945-devel mailing list
>> >[email protected]
>> >https://lists.sourceforge.net/lists/listinfo/ipw3945-devel
>> >--
>> To unsubscribe from this list: send the line "unsubscribe
>linux-wireless" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>

2010-02-11 20:26:09

by Wey-Yi Guy

[permalink] [raw]
Subject: RE: [ipw3945-devel] [PATCH 05/12] iwlwifi: remove unused op-code in PHY Calibration command

Hi Ben,

this is per Giora's request to remove unused calibration command. so we
will not alarm external to play with those commands.

we can add those back in if we are going to use it.

Wey

On Thu, 2010-02-11 at 12:17 -0800, Cahill, Ben M wrote:
> NACK. Keep them around; we may use in the future.
>
> -- Ben --
>
> >-----Original Message-----
> >From: Reinette Chatre [mailto:[email protected]]
> >Sent: Thursday, February 11, 2010 1:42 PM
> >To: [email protected]
> >Cc: Chatre, Reinette; [email protected];
> >[email protected]
> >Subject: [ipw3945-devel] [PATCH 05/12] iwlwifi: remove unused
> >op-code in PHY Calibration command
> >
> >From: Wey-Yi Guy <[email protected]>
> >
> >Number of calibration op-code are not used by driver, remove those from
> >iwl-commands.h
> >
> >Signed-off-by: Wey-Yi Guy <[email protected]>
> >Signed-off-by: Reinette Chatre <[email protected]>
> >---
> > drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ----
> > 1 files changed, 0 insertions(+), 4 deletions(-)
> >
> >diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h
> >b/drivers/net/wireless/iwlwifi/iwl-commands.h
> >index c2f31eb..ab3c77b 100644
> >--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
> >+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
> >@@ -3470,11 +3470,7 @@ enum {
> > IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
> > IWL_PHY_CALIBRATE_DC_CMD = 8,
> > IWL_PHY_CALIBRATE_LO_CMD = 9,
> >- IWL_PHY_CALIBRATE_RX_BB_CMD = 10,
> > IWL_PHY_CALIBRATE_TX_IQ_CMD = 11,
> >- IWL_PHY_CALIBRATE_RX_IQ_CMD = 12,
> >- IWL_PHY_CALIBRATION_NOISE_CMD = 13,
> >- IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
> > IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
> > IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
> > IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
> >--
> >1.6.3.3
> >
> >
> >---------------------------------------------------------------
> >---------------
> >SOLARIS 10 is the OS for Data Centers - provides features such
> >as DTrace,
> >Predictive Self Healing and Award Winning ZFS. Get Solaris 10 NOW
> >http://p.sf.net/sfu/solaris-dev2dev
> >_______________________________________________
> >Ipw3945-devel mailing list
> >[email protected]
> >https://lists.sourceforge.net/lists/listinfo/ipw3945-devel
> >--
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html