aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/realtek_cr.c
diff options
context:
space:
mode:
authoredwin_rong <edwin_rong@realsil.com.cn>2011-09-16 04:53:37 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-09-18 04:51:34 -0400
commit45e1892e70b85d251b2e69f4122a04e509ebdf00 (patch)
tree7485f2e2bcff2e04204409535c19b5fec32c5702 /drivers/usb/storage/realtek_cr.c
parent2394d67e446bf616a0885167d5f0d397bdacfdfc (diff)
USB: Realtek cr: Fix driver freeze issue
After auto-delink command is triggered, the CSW won't be sent back to host side, in which scenario, the USB Mass Storage driver will wait for the completion of the URB for MAX_SCHEDULE_TIMEOUT. Signed-off-by: edwin_rong <edwin_rong@realsil.com.cn> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/storage/realtek_cr.c')
-rw-r--r--drivers/usb/storage/realtek_cr.c81
1 files changed, 77 insertions, 4 deletions
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index 232167ad4781..f664c865e71e 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -293,6 +293,52 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,
293 return USB_STOR_TRANSPORT_ERROR; 293 return USB_STOR_TRANSPORT_ERROR;
294} 294}
295 295
296static int rts51x_bulk_transport_special(struct us_data *us, u8 lun,
297 u8 *cmd, int cmd_len, u8 *buf, int buf_len,
298 enum dma_data_direction dir, int *act_len)
299{
300 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
301 struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
302 int result;
303 unsigned int cswlen;
304 unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
305
306 /* set up the command wrapper */
307 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
308 bcb->DataTransferLength = cpu_to_le32(buf_len);
309 bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0;
310 bcb->Tag = ++us->tag;
311 bcb->Lun = lun;
312 bcb->Length = cmd_len;
313
314 /* copy the command payload */
315 memset(bcb->CDB, 0, sizeof(bcb->CDB));
316 memcpy(bcb->CDB, cmd, bcb->Length);
317
318 /* send it to out endpoint */
319 result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
320 bcb, cbwlen, NULL);
321 if (result != USB_STOR_XFER_GOOD)
322 return USB_STOR_TRANSPORT_ERROR;
323
324 /* DATA STAGE */
325 /* send/receive data payload, if there is any */
326
327 if (buf && buf_len) {
328 unsigned int pipe = (dir == DMA_FROM_DEVICE) ?
329 us->recv_bulk_pipe : us->send_bulk_pipe;
330 result = usb_stor_bulk_transfer_buf(us, pipe,
331 buf, buf_len, NULL);
332 if (result == USB_STOR_XFER_ERROR)
333 return USB_STOR_TRANSPORT_ERROR;
334 }
335
336 /* get CSW for device status */
337 result = usb_bulk_msg(us->pusb_dev, us->recv_bulk_pipe, bcs,
338 US_BULK_CS_WRAP_LEN, &cswlen, 250);
339 return result;
340}
341
296/* Determine what the maximum LUN supported is */ 342/* Determine what the maximum LUN supported is */
297static int rts51x_get_max_lun(struct us_data *us) 343static int rts51x_get_max_lun(struct us_data *us)
298{ 344{
@@ -459,6 +505,29 @@ static int enable_oscillator(struct us_data *us)
459 return 0; 505 return 0;
460} 506}
461 507
508static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len)
509{
510 int retval;
511 u16 addr = 0xFE47;
512 u8 cmnd[12] = {0};
513
514 US_DEBUGP("%s, addr = 0x%x, len = %d\n", __FUNCTION__, addr, len);
515
516 cmnd[0] = 0xF0;
517 cmnd[1] = 0x0E;
518 cmnd[2] = (u8)(addr >> 8);
519 cmnd[3] = (u8)addr;
520 cmnd[4] = (u8)(len >> 8);
521 cmnd[5] = (u8)len;
522
523 retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL);
524 if (retval != USB_STOR_TRANSPORT_GOOD) {
525 return -EIO;
526 }
527
528 return 0;
529}
530
462static int do_config_autodelink(struct us_data *us, int enable, int force) 531static int do_config_autodelink(struct us_data *us, int enable, int force)
463{ 532{
464 int retval; 533 int retval;
@@ -479,7 +548,8 @@ static int do_config_autodelink(struct us_data *us, int enable, int force)
479 548
480 US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value); 549 US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value);
481 550
482 retval = rts51x_write_mem(us, 0xFE47, &value, 1); 551 /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */
552 retval = __do_config_autodelink(us, &value, 1);
483 if (retval < 0) 553 if (retval < 0)
484 return -EIO; 554 return -EIO;
485 555
@@ -511,7 +581,8 @@ static int config_autodelink_after_power_on(struct us_data *us)
511 581
512 SET_BIT(value, 7); 582 SET_BIT(value, 7);
513 583
514 retval = rts51x_write_mem(us, 0xFE47, &value, 1); 584 /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */
585 retval = __do_config_autodelink(us, &value, 1);
515 if (retval < 0) 586 if (retval < 0)
516 return -EIO; 587 return -EIO;
517 588
@@ -532,7 +603,8 @@ static int config_autodelink_after_power_on(struct us_data *us)
532 CLR_BIT(value, 7); 603 CLR_BIT(value, 7);
533 } 604 }
534 605
535 retval = rts51x_write_mem(us, 0xFE47, &value, 1); 606 /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */
607 retval = __do_config_autodelink(us, &value, 1);
536 if (retval < 0) 608 if (retval < 0)
537 return -EIO; 609 return -EIO;
538 610
@@ -609,7 +681,8 @@ static int config_autodelink_before_power_down(struct us_data *us)
609 if (CHECK_ID(chip, 0x0138, 0x3882)) 681 if (CHECK_ID(chip, 0x0138, 0x3882))
610 SET_BIT(value, 2); 682 SET_BIT(value, 2);
611 683
612 retval = rts51x_write_mem(us, 0xFE47, &value, 1); 684 /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */
685 retval = __do_config_autodelink(us, &value, 1);
613 if (retval < 0) 686 if (retval < 0)
614 return -EIO; 687 return -EIO;
615 } 688 }