mirror of https://gitee.com/openkylin/linux.git
[Bug 455] Fix frequent channel change generates firmware fatal error.
Because of the frequent channel change, it is possible that when we are try to associate with channel 1 (authenticated but not associated). Another channel change comes at this time, then the driver will issue disassociate command to the firmware which will cause the fatal error. It seems that the association/disassociation procedure should not be interrupted. The patch attached adds test on STATUS_ASSOCIATING | STATUS_DISASSOCIATING in ipw_send_cmd(), when ensures that commands will not be sent to firmware when we are in these two status. Signed-off-by: Hong Liu <hong.liu@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com>
This commit is contained in:
parent
a0e04ab360
commit
7b99659f97
|
@ -1884,6 +1884,18 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->status & STATUS_ASSOCIATING) {
|
||||||
|
IPW_DEBUG_HC("abandon a command while associating\n");
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->status & STATUS_DISASSOCIATING) {
|
||||||
|
IPW_DEBUG_HC("abandon a command while disassociating\n");
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
priv->status |= STATUS_HCMD_ACTIVE;
|
priv->status |= STATUS_HCMD_ACTIVE;
|
||||||
|
|
||||||
if (priv->cmdlog) {
|
if (priv->cmdlog) {
|
||||||
|
@ -3671,7 +3683,13 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!(priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED))) {
|
if (priv->status & STATUS_ASSOCIATING) {
|
||||||
|
IPW_DEBUG_ASSOC("Disassociating while associating.\n");
|
||||||
|
queue_work(priv->workqueue, &priv->disassociate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(priv->status & STATUS_ASSOCIATED)) {
|
||||||
IPW_DEBUG_ASSOC("Disassociating while not associated.\n");
|
IPW_DEBUG_ASSOC("Disassociating while not associated.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3681,9 +3699,6 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
|
||||||
MAC_ARG(priv->assoc_request.bssid),
|
MAC_ARG(priv->assoc_request.bssid),
|
||||||
priv->assoc_request.channel);
|
priv->assoc_request.channel);
|
||||||
|
|
||||||
priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
|
|
||||||
priv->status |= STATUS_DISASSOCIATING;
|
|
||||||
|
|
||||||
if (quiet)
|
if (quiet)
|
||||||
priv->assoc_request.assoc_type = HC_DISASSOC_QUIET;
|
priv->assoc_request.assoc_type = HC_DISASSOC_QUIET;
|
||||||
else
|
else
|
||||||
|
@ -3695,6 +3710,9 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
|
||||||
|
priv->status |= STATUS_DISASSOCIATING;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ipw_disassociate(void *data)
|
static int ipw_disassociate(void *data)
|
||||||
|
@ -7625,8 +7643,6 @@ static int ipw_associate_network(struct ipw_priv *priv,
|
||||||
*/
|
*/
|
||||||
priv->channel = network->channel;
|
priv->channel = network->channel;
|
||||||
memcpy(priv->bssid, network->bssid, ETH_ALEN);
|
memcpy(priv->bssid, network->bssid, ETH_ALEN);
|
||||||
priv->status |= STATUS_ASSOCIATING;
|
|
||||||
priv->status &= ~STATUS_SECURITY_UPDATED;
|
|
||||||
|
|
||||||
priv->assoc_network = network;
|
priv->assoc_network = network;
|
||||||
|
|
||||||
|
@ -7640,6 +7656,9 @@ static int ipw_associate_network(struct ipw_priv *priv,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->status |= STATUS_ASSOCIATING;
|
||||||
|
priv->status &= ~STATUS_SECURITY_UPDATED;
|
||||||
|
|
||||||
IPW_DEBUG(IPW_DL_STATE, "associating: '%s' " MAC_FMT " \n",
|
IPW_DEBUG(IPW_DL_STATE, "associating: '%s' " MAC_FMT " \n",
|
||||||
escape_essid(priv->essid, priv->essid_len),
|
escape_essid(priv->essid, priv->essid_len),
|
||||||
MAC_ARG(priv->bssid));
|
MAC_ARG(priv->bssid));
|
||||||
|
|
Loading…
Reference in New Issue