aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavan Savoy <pavan_savoy@ti.com>2011-02-04 03:23:14 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-04 15:41:21 -0500
commit6d71ba2105a1d8c1712cdfcf46fc6040e4707cb9 (patch)
tree193b01abd397a5ebf5bcbdb6a02e51f8757582a2
parentef04d121f030329aae0c2d3ec22beea0c5cbcfd3 (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.c15
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}