aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith.Manoharan@atheros.com <Sujith.Manoharan@atheros.com>2010-05-11 06:54:43 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-05-12 16:39:06 -0400
commitd8c49ffb2e2a47b23fec7f469435e7b112e2e569 (patch)
treee10f7f1318597dd47982e2043355ff2d89173728
parent47fce026d5de5d11e161da73208171e9c91b659a (diff)
ath9k_htc: Fix target ready race condition
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>
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.h1
3 files changed, 11 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 17111fc1d2cc..dc015077a8d9 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -81,6 +81,11 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
81{ 81{
82 int time_left; 82 int time_left;
83 83
84 if (atomic_read(&priv->htc->tgt_ready) > 0) {
85 atomic_dec(&priv->htc->tgt_ready);
86 return 0;
87 }
88
84 /* Firmware can take up to 50ms to get ready, to be safe use 1 second */ 89 /* Firmware can take up to 50ms to get ready, to be safe use 1 second */
85 time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ); 90 time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ);
86 if (!time_left) { 91 if (!time_left) {
@@ -88,6 +93,8 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
88 return -ETIMEDOUT; 93 return -ETIMEDOUT;
89 } 94 }
90 95
96 atomic_dec(&priv->htc->tgt_ready);
97
91 return 0; 98 return 0;
92} 99}
93 100
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index 2c8006ae2786..e86e1728c8de 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -95,6 +95,7 @@ static void htc_process_target_rdy(struct htc_target *target,
95 endpoint = &target->endpoint[ENDPOINT0]; 95 endpoint = &target->endpoint[ENDPOINT0];
96 endpoint->service_id = HTC_CTRL_RSVD_SVC; 96 endpoint->service_id = HTC_CTRL_RSVD_SVC;
97 endpoint->max_msglen = HTC_MAX_CONTROL_MESSAGE_LENGTH; 97 endpoint->max_msglen = HTC_MAX_CONTROL_MESSAGE_LENGTH;
98 atomic_inc(&target->tgt_ready);
98 complete(&target->target_wait); 99 complete(&target->target_wait);
99} 100}
100 101
@@ -451,6 +452,8 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle,
451 endpoint->ul_pipeid = hif->control_ul_pipe; 452 endpoint->ul_pipeid = hif->control_ul_pipe;
452 endpoint->dl_pipeid = hif->control_dl_pipe; 453 endpoint->dl_pipeid = hif->control_dl_pipe;
453 454
455 atomic_set(&target->tgt_ready, 0);
456
454 return target; 457 return target;
455} 458}
456 459
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h
index d216c0f4d168..4f1cdb003cce 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.h
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.h
@@ -147,6 +147,7 @@ struct htc_target {
147 u16 credits; 147 u16 credits;
148 u16 credit_size; 148 u16 credit_size;
149 u8 htc_flags; 149 u8 htc_flags;
150 atomic_t tgt_ready;
150}; 151};
151 152
152enum htc_msg_id { 153enum htc_msg_id {