diff options
author | Sujith.Manoharan@atheros.com <Sujith.Manoharan@atheros.com> | 2010-05-11 06:54:43 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-05-12 16:39:06 -0400 |
commit | d8c49ffb2e2a47b23fec7f469435e7b112e2e569 (patch) | |
tree | e10f7f1318597dd47982e2043355ff2d89173728 | |
parent | 47fce026d5de5d11e161da73208171e9c91b659a (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.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_hst.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_hst.h | 1 |
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 | ||
152 | enum htc_msg_id { | 153 | enum htc_msg_id { |