ath9k_htc: Fix target ready race condition
authorSujith.Manoharan@atheros.com <Sujith.Manoharan@atheros.com>
Tue, 11 May 2010 10:54:43 +0000 (16:24 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 12 May 2010 20:39:06 +0000 (16:39 -0400)
The ready message from the target could be processed
before the host HW init has completed. In this case,
htc_process_target_rdy() would assume the target has timed
out, when it hasn't. Fix this by checking if the target
has sent the ready message properly.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_hst.c
drivers/net/wireless/ath/ath9k/htc_hst.h

index 17111fc1d2cc59a71f8d84c6c14df76ea43801ff..dc015077a8d908ce17db5bc10e1cdb8a80d725b8 100644 (file)
@@ -81,6 +81,11 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
 {
        int time_left;
 
+       if (atomic_read(&priv->htc->tgt_ready) > 0) {
+               atomic_dec(&priv->htc->tgt_ready);
+               return 0;
+       }
+
        /* Firmware can take up to 50ms to get ready, to be safe use 1 second */
        time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ);
        if (!time_left) {
@@ -88,6 +93,8 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
                return -ETIMEDOUT;
        }
 
+       atomic_dec(&priv->htc->tgt_ready);
+
        return 0;
 }
 
index 2c8006ae27869bb02459e644677ba8913d253a32..e86e1728c8de1fe44fe850fab956528caeeca37c 100644 (file)
@@ -95,6 +95,7 @@ static void htc_process_target_rdy(struct htc_target *target,
        endpoint = &target->endpoint[ENDPOINT0];
        endpoint->service_id = HTC_CTRL_RSVD_SVC;
        endpoint->max_msglen = HTC_MAX_CONTROL_MESSAGE_LENGTH;
+       atomic_inc(&target->tgt_ready);
        complete(&target->target_wait);
 }
 
@@ -451,6 +452,8 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle,
        endpoint->ul_pipeid = hif->control_ul_pipe;
        endpoint->dl_pipeid = hif->control_dl_pipe;
 
+       atomic_set(&target->tgt_ready, 0);
+
        return target;
 }
 
index d216c0f4d168d2c118ada3dd6fd850d947b061c1..4f1cdb003ccecc944cd0eb9843ad989aa2f6bdbd 100644 (file)
@@ -147,6 +147,7 @@ struct htc_target {
        u16 credits;
        u16 credit_size;
        u8 htc_flags;
+       atomic_t tgt_ready;
 };
 
 enum htc_msg_id {