aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorHong Liu <hong.liu@intel.com>2005-08-25 05:36:13 -0400
committerJames Ketrenos <jketreno@linux.intel.com>2005-11-07 18:51:11 -0500
commit7b99659f97ca20e5f1ea56253a9449d278d825d5 (patch)
tree318b810e66466299874004b202fa7ee9a4538878 /drivers/net
parenta0e04ab36048eb1c3da2524b5b0b802b6ab064f0 (diff)
[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>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ipw2200.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 9ced5b778a77..4cdb4748b761 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -1884,6 +1884,18 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
1884 return -EAGAIN; 1884 return -EAGAIN;
1885 } 1885 }
1886 1886
1887 if (priv->status & STATUS_ASSOCIATING) {
1888 IPW_DEBUG_HC("abandon a command while associating\n");
1889 spin_unlock_irqrestore(&priv->lock, flags);
1890 return -1;
1891 }
1892
1893 if (priv->status & STATUS_DISASSOCIATING) {
1894 IPW_DEBUG_HC("abandon a command while disassociating\n");
1895 spin_unlock_irqrestore(&priv->lock, flags);
1896 return -1;
1897 }
1898
1887 priv->status |= STATUS_HCMD_ACTIVE; 1899 priv->status |= STATUS_HCMD_ACTIVE;
1888 1900
1889 if (priv->cmdlog) { 1901 if (priv->cmdlog) {
@@ -3671,7 +3683,13 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
3671{ 3683{
3672 int err; 3684 int err;
3673 3685
3674 if (!(priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED))) { 3686 if (priv->status & STATUS_ASSOCIATING) {
3687 IPW_DEBUG_ASSOC("Disassociating while associating.\n");
3688 queue_work(priv->workqueue, &priv->disassociate);
3689 return;
3690 }
3691
3692 if (!(priv->status & STATUS_ASSOCIATED)) {
3675 IPW_DEBUG_ASSOC("Disassociating while not associated.\n"); 3693 IPW_DEBUG_ASSOC("Disassociating while not associated.\n");
3676 return; 3694 return;
3677 } 3695 }
@@ -3681,9 +3699,6 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
3681 MAC_ARG(priv->assoc_request.bssid), 3699 MAC_ARG(priv->assoc_request.bssid),
3682 priv->assoc_request.channel); 3700 priv->assoc_request.channel);
3683 3701
3684 priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
3685 priv->status |= STATUS_DISASSOCIATING;
3686
3687 if (quiet) 3702 if (quiet)
3688 priv->assoc_request.assoc_type = HC_DISASSOC_QUIET; 3703 priv->assoc_request.assoc_type = HC_DISASSOC_QUIET;
3689 else 3704 else
@@ -3695,6 +3710,9 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
3695 return; 3710 return;
3696 } 3711 }
3697 3712
3713 priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
3714 priv->status |= STATUS_DISASSOCIATING;
3715
3698} 3716}
3699 3717
3700static int ipw_disassociate(void *data) 3718static int ipw_disassociate(void *data)
@@ -7625,8 +7643,6 @@ static int ipw_associate_network(struct ipw_priv *priv,
7625 */ 7643 */
7626 priv->channel = network->channel; 7644 priv->channel = network->channel;
7627 memcpy(priv->bssid, network->bssid, ETH_ALEN); 7645 memcpy(priv->bssid, network->bssid, ETH_ALEN);
7628 priv->status |= STATUS_ASSOCIATING;
7629 priv->status &= ~STATUS_SECURITY_UPDATED;
7630 7646
7631 priv->assoc_network = network; 7647 priv->assoc_network = network;
7632 7648
@@ -7640,6 +7656,9 @@ static int ipw_associate_network(struct ipw_priv *priv,
7640 return err; 7656 return err;
7641 } 7657 }
7642 7658
7659 priv->status |= STATUS_ASSOCIATING;
7660 priv->status &= ~STATUS_SECURITY_UPDATED;
7661
7643 IPW_DEBUG(IPW_DL_STATE, "associating: '%s' " MAC_FMT " \n", 7662 IPW_DEBUG(IPW_DL_STATE, "associating: '%s' " MAC_FMT " \n",
7644 escape_essid(priv->essid, priv->essid_len), 7663 escape_essid(priv->essid, priv->essid_len),
7645 MAC_ARG(priv->bssid)); 7664 MAC_ARG(priv->bssid));