mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-08 06:26:39 +07:00
ipw2200: Fix race condition in the command completion acknowledge
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 roaming (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> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
8db4c7e25d
commit
dd44731989
@ -2191,6 +2191,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) {
|
||||
@ -2232,10 +2233,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) {
|
||||
|
Loading…
Reference in New Issue
Block a user