linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [FYI] iwlagn: do not use interruptible waits
@ 2011-09-09 12:14 Johannes Berg
  2011-09-09 12:19 ` [FYI] iwlagn: fix command queue timeout Johannes Berg
  0 siblings, 1 reply; 4+ messages in thread
From: Johannes Berg @ 2011-09-09 12:14 UTC (permalink / raw)
  To: linux-wireless; +Cc: Stanislaw Gruszka

I just submitted the following patch to our internal tree:



From: Johannes Berg <johannes.berg@intel.com>

Since the dawn of its time, iwlwifi has used
interruptible waits to wait for synchronous
commands and firmware loading.

This leads to "interesting" bugs, because it
can't actually handle the interruptions; for
example when a command sending is interrupted
it will assume the command completed fully,
and then leave it pending, which leads to all
kinds of trouble when the command finishes
later.

Since there's no easy way to gracefully deal
with interruptions, fix the driver to not use
interruptible waits.

This at least fixes the error
iwlagn 0000:02:00.0: Error: Response NULL in  'REPLY_SCAN_ABORT_CMD'

I have seen in P2P testing, but it is likely
that there are other errors caused by this.

Cc: Stanislaw Gruszka <sgruszka@redhat.com>
Cc: stable@kernel.org [2.6.24+]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn-ucode.c     |    9 ++-------
 drivers/net/wireless/iwlwifi/iwl-core.c          |    2 +-
 drivers/net/wireless/iwlwifi/iwl-rx.c            |    2 +-
 drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c |    4 ++--
 drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c |    4 ++--
 5 files changed, 8 insertions(+), 13 deletions(-)

--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c	2011-09-09 13:59:41.000000000 +0200
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c	2011-09-09 14:00:46.000000000 +0200
@@ -114,13 +114,8 @@ static int iwlagn_load_section(struct iw
 		FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
 
 	IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
-	ret = wait_event_interruptible_timeout(priv->shrd->wait_command_queue,
-					priv->ucode_write_complete, 5 * HZ);
-	if (ret == -ERESTARTSYS) {
-		IWL_ERR(priv, "Could not load the %s uCode section due "
-			"to interrupt\n", name);
-		return ret;
-	}
+	ret = wait_event_timeout(priv->shrd->wait_command_queue,
+				 priv->ucode_write_complete, 5 * HZ);
 	if (!ret) {
 		IWL_ERR(priv, "Could not load the %s uCode section\n",
 			name);
--- a/drivers/net/wireless/iwlwifi/iwl-core.c	2011-09-09 13:59:41.000000000 +0200
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c	2011-09-09 14:01:12.000000000 +0200
@@ -869,7 +869,7 @@ void iwlagn_fw_error(struct iwl_priv *pr
 	 * commands by clearing the ready bit */
 	clear_bit(STATUS_READY, &priv->shrd->status);
 
-	wake_up_interruptible(&priv->shrd->wait_command_queue);
+	wake_up(&priv->shrd->wait_command_queue);
 
 	if (!ondemand) {
 		/*
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c	2011-09-09 13:59:41.000000000 +0200
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c	2011-09-09 14:00:30.000000000 +0200
@@ -644,7 +644,7 @@ static void iwl_rx_card_state_notif(stru
 		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
 			test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
 	else
-		wake_up_interruptible(&priv->shrd->wait_command_queue);
+		wake_up(&priv->shrd->wait_command_queue);
 }
 
 static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c	2011-09-09 13:59:41.000000000 +0200
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c	2011-09-09 14:01:13.000000000 +0200
@@ -657,7 +657,7 @@ static void iwl_irq_handle_error(struct
 		 */
 		clear_bit(STATUS_READY, &trans->shrd->status);
 		clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
-		wake_up_interruptible(&priv->shrd->wait_command_queue);
+		wake_up(&priv->shrd->wait_command_queue);
 		IWL_ERR(trans, "RF is used by WiMAX\n");
 		return;
 	}
@@ -1098,7 +1098,7 @@ void iwl_irq_tasklet(struct iwl_trans *t
 		handled |= CSR_INT_BIT_FH_TX;
 		/* Wake up uCode load routine, now that load is complete */
 		priv(trans)->ucode_write_complete = 1;
-		wake_up_interruptible(&trans->shrd->wait_command_queue);
+		wake_up(&trans->shrd->wait_command_queue);
 	}
 
 	if (inta & ~handled) {
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c	2011-09-09 13:59:41.000000000 +0200
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c	2011-09-09 14:01:07.000000000 +0200
@@ -948,7 +948,7 @@ void iwl_tx_cmd_complete(struct iwl_tran
 		clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
 		IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
 			       get_cmd_string(cmd->hdr.cmd));
-		wake_up_interruptible(&trans->shrd->wait_command_queue);
+		wake_up(&trans->shrd->wait_command_queue);
 	}
 
 	meta->flags = 0;
@@ -1034,7 +1034,7 @@ static int iwl_send_cmd_sync(struct iwl_
 		return ret;
 	}
 
-	ret = wait_event_interruptible_timeout(trans->shrd->wait_command_queue,
+	ret = wait_event_timeout(trans->shrd->wait_command_queue,
 			!test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status),
 			HOST_COMPLETE_TIMEOUT);
 	if (!ret) {



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [FYI] iwlagn: fix command queue timeout
  2011-09-09 12:14 [FYI] iwlagn: do not use interruptible waits Johannes Berg
@ 2011-09-09 12:19 ` Johannes Berg
  2011-09-09 12:21   ` Johannes Berg
  0 siblings, 1 reply; 4+ messages in thread
From: Johannes Berg @ 2011-09-09 12:19 UTC (permalink / raw)
  To: linux-wireless; +Cc: Stanislaw Gruszka

And here's another one -- I think iwlegacy has the same bug which
probably means I can answer my question below with yes, it definitely
does need to go to stable ...



From: Johannes Berg <johannes.berg@intel.com>

If the command queue is constantly busy,
which can happen in P2P, the hangcheck
timer will frequently find a command in
it and will eventually reset the device
because nothing sets the timestamp for
this queue when commands are processed.

Fix this by setting the timestamp when
a command completes.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
It's possible this needs to go to stable?

 drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c |    2 ++
 1 file changed, 2 insertions(+)

--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c	2011-09-09 13:55:03.000000000 +0200
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c	2011-09-09 13:55:26.000000000 +0200
@@ -928,6 +928,8 @@ void iwl_tx_cmd_complete(struct iwl_tran
 	cmd = txq->cmd[cmd_index];
 	meta = &txq->meta[cmd_index];
 
+	txq->time_stamp = jiffies;
+
 	iwlagn_unmap_tfd(trans, meta, &txq->tfds[index],
 			 DMA_BIDIRECTIONAL);
 



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [FYI] iwlagn: fix command queue timeout
  2011-09-09 12:19 ` [FYI] iwlagn: fix command queue timeout Johannes Berg
@ 2011-09-09 12:21   ` Johannes Berg
  2011-09-09 14:18     ` wwguy
  0 siblings, 1 reply; 4+ messages in thread
From: Johannes Berg @ 2011-09-09 12:21 UTC (permalink / raw)
  To: linux-wireless; +Cc: Stanislaw Gruszka, wey-yi.w.guy

On Fri, 2011-09-09 at 14:19 +0200, Johannes Berg wrote:

> Fix this by setting the timestamp when
> a command completes.

FWIW, I don't think this is a really good fix, I think it should have a
timer per queue that never fires, and when it fires the queue is stuck
-- i.e. mod the timer into the future whenever a command/tx frame
completes and cancel the timer when the queue goes empty (and start it
if it's pending when we enqueue something)

johannes


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [FYI] iwlagn: fix command queue timeout
  2011-09-09 12:21   ` Johannes Berg
@ 2011-09-09 14:18     ` wwguy
  0 siblings, 0 replies; 4+ messages in thread
From: wwguy @ 2011-09-09 14:18 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org, Stanislaw Gruszka

On Fri, 2011-09-09 at 05:21 -0700, Johannes Berg wrote:
> On Fri, 2011-09-09 at 14:19 +0200, Johannes Berg wrote:
> 
> > Fix this by setting the timestamp when
> > a command completes.
> 
> FWIW, I don't think this is a really good fix, I think it should have a
> timer per queue that never fires, and when it fires the queue is stuck
> -- i.e. mod the timer into the future whenever a command/tx frame
> completes and cancel the timer when the queue goes empty (and start it
> if it's pending when we enqueue something)
> 
Agree, we need better fix, I saw this happen number of times on my
system which does not have P2P and no traffic. One time even just
loading the iwlagn module; not sure it is the same case.

Thanks
Wey
> 



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-09-09 14:23 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-09 12:14 [FYI] iwlagn: do not use interruptible waits Johannes Berg
2011-09-09 12:19 ` [FYI] iwlagn: fix command queue timeout Johannes Berg
2011-09-09 12:21   ` Johannes Berg
2011-09-09 14:18     ` wwguy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).