69 lines
2.4 KiB
Diff
69 lines
2.4 KiB
Diff
|
Driver incorrectly validates command completion: instead of waiting
|
||
|
for a command to be acknowledged it continues execution. Most of the
|
||
|
time driver gets acknowledge of the command completion in a tasklet
|
||
|
before it executes the next one. But sometimes it sends the next
|
||
|
command before it gets acknowledge for the previous one. In such a
|
||
|
case one of the following error messages appear in the log:
|
||
|
|
||
|
Failed to send SYSTEM_CONFIG: Already sending a command.
|
||
|
Failed to send ASSOCIATE: Already sending a command.
|
||
|
Failed to send TX_POWER: Already sending a command.
|
||
|
|
||
|
After that you need to reload the driver to get it working again.
|
||
|
|
||
|
This bug occurs during roammaping (reported by Sam Varshavchik)
|
||
|
https://bugzilla.redhat.com/show_bug.cgi?id=738508
|
||
|
and machine booting (reported by Tom Gundersen and Mads Kiilerich)
|
||
|
https://bugs.archlinux.org/task/28097
|
||
|
https://bugzilla.redhat.com/show_bug.cgi?id=802106
|
||
|
|
||
|
This patch doesn't fix the delay issue during firmware load.
|
||
|
But at least device now works as usual after boot.
|
||
|
|
||
|
Cc: stable@kernel.org
|
||
|
Signed-off-by: Stanislav Yakovlev <stas.yakovlev@gmail.com>
|
||
|
---
|
||
|
drivers/net/wireless/ipw2x00/ipw2200.c | 13 ++++++++++++-
|
||
|
1 files changed, 12 insertions(+), 1 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
|
||
|
index 4130802..8cbafa5 100644
|
||
|
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
|
||
|
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
|
||
|
@@ -2192,6 +2192,7 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
|
||
|
{
|
||
|
int rc = 0;
|
||
|
unsigned long flags;
|
||
|
+ unsigned long now, end;
|
||
|
|
||
|
spin_lock_irqsave(&priv->lock, flags);
|
||
|
if (priv->status & STATUS_HCMD_ACTIVE) {
|
||
|
@@ -2233,10 +2234,20 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
|
||
|
}
|
||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||
|
|
||
|
+ now = jiffies;
|
||
|
+ end = now + HOST_COMPLETE_TIMEOUT;
|
||
|
+again:
|
||
|
rc = wait_event_interruptible_timeout(priv->wait_command_queue,
|
||
|
!(priv->
|
||
|
status & STATUS_HCMD_ACTIVE),
|
||
|
- HOST_COMPLETE_TIMEOUT);
|
||
|
+ end - now);
|
||
|
+ if (rc < 0) {
|
||
|
+ now = jiffies;
|
||
|
+ if (time_before(now, end))
|
||
|
+ goto again;
|
||
|
+ rc = 0;
|
||
|
+ }
|
||
|
+
|
||
|
if (rc == 0) {
|
||
|
spin_lock_irqsave(&priv->lock, flags);
|
||
|
if (priv->status & STATUS_HCMD_ACTIVE) {
|
||
|
--
|
||
|
1.7.2.5
|
||
|
|
||
|
--
|
||
|
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
|
||
|
the body of a message to majordomo@vger.kernel.org
|
||
|
More majordomo info at http://vger.kernel.org/majordomo-info.html
|