diff options
author | Pavan Savoy <pavan_savoy@ti.com> | 2011-02-04 03:23:14 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-02-04 15:41:21 -0500 |
commit | 6d71ba2105a1d8c1712cdfcf46fc6040e4707cb9 (patch) | |
tree | 193b01abd397a5ebf5bcbdb6a02e51f8757582a2 | |
parent | ef04d121f030329aae0c2d3ec22beea0c5cbcfd3 (diff) |
drivers:misc: ti-st: fix hci-ll on wake_ind collision
Where file-transfer stops/pauses in between, is
result of a HCI-LL anamoly in ST LL driver.
ST LL did not copy the contents of WaitQ into the TxQ, when a WAKEUP_IND
collision happened.
Make also sure, that the copying mechanism is safe, by wrapping it around
spin locks inside st_int_recv().
This was easily reproduced when the sleep timeout was reduced to 100ms
for HCI-LL.
Signed-off-by: Pavan Savoy <pavan_savoy@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/misc/ti-st/st_core.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index dd2c879faff6..f0d24d852078 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c | |||
@@ -236,6 +236,7 @@ void st_int_recv(void *disc_data, | |||
236 | int len = 0, type = 0; | 236 | int len = 0, type = 0; |
237 | unsigned char *plen; | 237 | unsigned char *plen; |
238 | struct st_data_s *st_gdata = (struct st_data_s *)disc_data; | 238 | struct st_data_s *st_gdata = (struct st_data_s *)disc_data; |
239 | unsigned long flags; | ||
239 | 240 | ||
240 | ptr = (char *)data; | 241 | ptr = (char *)data; |
241 | /* tty_receive sent null ? */ | 242 | /* tty_receive sent null ? */ |
@@ -248,6 +249,7 @@ void st_int_recv(void *disc_data, | |||
248 | "rx_count %ld", count, st_gdata->rx_state, | 249 | "rx_count %ld", count, st_gdata->rx_state, |
249 | st_gdata->rx_count); | 250 | st_gdata->rx_count); |
250 | 251 | ||
252 | spin_lock_irqsave(&st_gdata->lock, flags); | ||
251 | /* Decode received bytes here */ | 253 | /* Decode received bytes here */ |
252 | while (count) { | 254 | while (count) { |
253 | if (st_gdata->rx_count) { | 255 | if (st_gdata->rx_count) { |
@@ -308,13 +310,25 @@ void st_int_recv(void *disc_data, | |||
308 | * sleep state received -- | 310 | * sleep state received -- |
309 | */ | 311 | */ |
310 | st_ll_sleep_state(st_gdata, *ptr); | 312 | st_ll_sleep_state(st_gdata, *ptr); |
313 | /* if WAKEUP_IND collides copy from waitq to txq | ||
314 | * and assume chip awake | ||
315 | */ | ||
316 | spin_unlock_irqrestore(&st_gdata->lock, flags); | ||
317 | if (st_ll_getstate(st_gdata) == ST_LL_AWAKE) | ||
318 | st_wakeup_ack(st_gdata, LL_WAKE_UP_ACK); | ||
319 | spin_lock_irqsave(&st_gdata->lock, flags); | ||
320 | |||
311 | ptr++; | 321 | ptr++; |
312 | count--; | 322 | count--; |
313 | continue; | 323 | continue; |
314 | case LL_WAKE_UP_ACK: | 324 | case LL_WAKE_UP_ACK: |
315 | pr_debug("PM packet"); | 325 | pr_debug("PM packet"); |
326 | |||
327 | spin_unlock_irqrestore(&st_gdata->lock, flags); | ||
316 | /* wake up ack received */ | 328 | /* wake up ack received */ |
317 | st_wakeup_ack(st_gdata, *ptr); | 329 | st_wakeup_ack(st_gdata, *ptr); |
330 | spin_lock_irqsave(&st_gdata->lock, flags); | ||
331 | |||
318 | ptr++; | 332 | ptr++; |
319 | count--; | 333 | count--; |
320 | continue; | 334 | continue; |
@@ -337,6 +351,7 @@ void st_int_recv(void *disc_data, | |||
337 | ptr++; | 351 | ptr++; |
338 | count--; | 352 | count--; |
339 | } | 353 | } |
354 | spin_unlock_irqrestore(&st_gdata->lock, flags); | ||
340 | pr_debug("done %s", __func__); | 355 | pr_debug("done %s", __func__); |
341 | return; | 356 | return; |
342 | } | 357 | } |