diff options
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r-- | drivers/usb/storage/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/storage/realtek_cr.c | 117 | ||||
-rw-r--r-- | drivers/usb/storage/transport.c | 34 | ||||
-rw-r--r-- | drivers/usb/storage/usb.c | 16 |
4 files changed, 140 insertions, 29 deletions
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index bedc4b9f2ac4..fe2d803a6347 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig | |||
@@ -42,7 +42,7 @@ config USB_STORAGE_REALTEK | |||
42 | 42 | ||
43 | config REALTEK_AUTOPM | 43 | config REALTEK_AUTOPM |
44 | bool "Realtek Card Reader autosuspend support" | 44 | bool "Realtek Card Reader autosuspend support" |
45 | depends on USB_STORAGE_REALTEK && CONFIG_PM_RUNTIME | 45 | depends on USB_STORAGE_REALTEK && PM_RUNTIME |
46 | default y | 46 | default y |
47 | 47 | ||
48 | config USB_STORAGE_DATAFAB | 48 | config USB_STORAGE_DATAFAB |
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 34adc4b42ceb..0ce5f79197e7 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/kthread.h> | 25 | #include <linux/kthread.h> |
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/version.h> | ||
29 | 28 | ||
30 | #include <scsi/scsi.h> | 29 | #include <scsi/scsi.h> |
31 | #include <scsi/scsi_cmnd.h> | 30 | #include <scsi/scsi_cmnd.h> |
@@ -293,6 +292,52 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, | |||
293 | return USB_STOR_TRANSPORT_ERROR; | 292 | return USB_STOR_TRANSPORT_ERROR; |
294 | } | 293 | } |
295 | 294 | ||
295 | static int rts51x_bulk_transport_special(struct us_data *us, u8 lun, | ||
296 | u8 *cmd, int cmd_len, u8 *buf, int buf_len, | ||
297 | enum dma_data_direction dir, int *act_len) | ||
298 | { | ||
299 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | ||
300 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | ||
301 | int result; | ||
302 | unsigned int cswlen; | ||
303 | unsigned int cbwlen = US_BULK_CB_WRAP_LEN; | ||
304 | |||
305 | /* set up the command wrapper */ | ||
306 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | ||
307 | bcb->DataTransferLength = cpu_to_le32(buf_len); | ||
308 | bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0; | ||
309 | bcb->Tag = ++us->tag; | ||
310 | bcb->Lun = lun; | ||
311 | bcb->Length = cmd_len; | ||
312 | |||
313 | /* copy the command payload */ | ||
314 | memset(bcb->CDB, 0, sizeof(bcb->CDB)); | ||
315 | memcpy(bcb->CDB, cmd, bcb->Length); | ||
316 | |||
317 | /* send it to out endpoint */ | ||
318 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
319 | bcb, cbwlen, NULL); | ||
320 | if (result != USB_STOR_XFER_GOOD) | ||
321 | return USB_STOR_TRANSPORT_ERROR; | ||
322 | |||
323 | /* DATA STAGE */ | ||
324 | /* send/receive data payload, if there is any */ | ||
325 | |||
326 | if (buf && buf_len) { | ||
327 | unsigned int pipe = (dir == DMA_FROM_DEVICE) ? | ||
328 | us->recv_bulk_pipe : us->send_bulk_pipe; | ||
329 | result = usb_stor_bulk_transfer_buf(us, pipe, | ||
330 | buf, buf_len, NULL); | ||
331 | if (result == USB_STOR_XFER_ERROR) | ||
332 | return USB_STOR_TRANSPORT_ERROR; | ||
333 | } | ||
334 | |||
335 | /* get CSW for device status */ | ||
336 | result = usb_bulk_msg(us->pusb_dev, us->recv_bulk_pipe, bcs, | ||
337 | US_BULK_CS_WRAP_LEN, &cswlen, 250); | ||
338 | return result; | ||
339 | } | ||
340 | |||
296 | /* Determine what the maximum LUN supported is */ | 341 | /* Determine what the maximum LUN supported is */ |
297 | static int rts51x_get_max_lun(struct us_data *us) | 342 | static int rts51x_get_max_lun(struct us_data *us) |
298 | { | 343 | { |
@@ -320,6 +365,11 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) | |||
320 | { | 365 | { |
321 | int retval; | 366 | int retval; |
322 | u8 cmnd[12] = { 0 }; | 367 | u8 cmnd[12] = { 0 }; |
368 | u8 *buf; | ||
369 | |||
370 | buf = kmalloc(len, GFP_NOIO); | ||
371 | if (buf == NULL) | ||
372 | return USB_STOR_TRANSPORT_ERROR; | ||
323 | 373 | ||
324 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); | 374 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); |
325 | 375 | ||
@@ -331,10 +381,14 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) | |||
331 | cmnd[5] = (u8) len; | 381 | cmnd[5] = (u8) len; |
332 | 382 | ||
333 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, | 383 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, |
334 | data, len, DMA_FROM_DEVICE, NULL); | 384 | buf, len, DMA_FROM_DEVICE, NULL); |
335 | if (retval != USB_STOR_TRANSPORT_GOOD) | 385 | if (retval != USB_STOR_TRANSPORT_GOOD) { |
386 | kfree(buf); | ||
336 | return -EIO; | 387 | return -EIO; |
388 | } | ||
337 | 389 | ||
390 | memcpy(data, buf, len); | ||
391 | kfree(buf); | ||
338 | return 0; | 392 | return 0; |
339 | } | 393 | } |
340 | 394 | ||
@@ -342,6 +396,12 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) | |||
342 | { | 396 | { |
343 | int retval; | 397 | int retval; |
344 | u8 cmnd[12] = { 0 }; | 398 | u8 cmnd[12] = { 0 }; |
399 | u8 *buf; | ||
400 | |||
401 | buf = kmalloc(len, GFP_NOIO); | ||
402 | if (buf == NULL) | ||
403 | return USB_STOR_TRANSPORT_ERROR; | ||
404 | memcpy(buf, data, len); | ||
345 | 405 | ||
346 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); | 406 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); |
347 | 407 | ||
@@ -353,7 +413,8 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) | |||
353 | cmnd[5] = (u8) len; | 413 | cmnd[5] = (u8) len; |
354 | 414 | ||
355 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, | 415 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, |
356 | data, len, DMA_TO_DEVICE, NULL); | 416 | buf, len, DMA_TO_DEVICE, NULL); |
417 | kfree(buf); | ||
357 | if (retval != USB_STOR_TRANSPORT_GOOD) | 418 | if (retval != USB_STOR_TRANSPORT_GOOD) |
358 | return -EIO; | 419 | return -EIO; |
359 | 420 | ||
@@ -365,6 +426,11 @@ static int rts51x_read_status(struct us_data *us, | |||
365 | { | 426 | { |
366 | int retval; | 427 | int retval; |
367 | u8 cmnd[12] = { 0 }; | 428 | u8 cmnd[12] = { 0 }; |
429 | u8 *buf; | ||
430 | |||
431 | buf = kmalloc(len, GFP_NOIO); | ||
432 | if (buf == NULL) | ||
433 | return USB_STOR_TRANSPORT_ERROR; | ||
368 | 434 | ||
369 | US_DEBUGP("%s, lun = %d\n", __func__, lun); | 435 | US_DEBUGP("%s, lun = %d\n", __func__, lun); |
370 | 436 | ||
@@ -372,10 +438,14 @@ static int rts51x_read_status(struct us_data *us, | |||
372 | cmnd[1] = 0x09; | 438 | cmnd[1] = 0x09; |
373 | 439 | ||
374 | retval = rts51x_bulk_transport(us, lun, cmnd, 12, | 440 | retval = rts51x_bulk_transport(us, lun, cmnd, 12, |
375 | status, len, DMA_FROM_DEVICE, actlen); | 441 | buf, len, DMA_FROM_DEVICE, actlen); |
376 | if (retval != USB_STOR_TRANSPORT_GOOD) | 442 | if (retval != USB_STOR_TRANSPORT_GOOD) { |
443 | kfree(buf); | ||
377 | return -EIO; | 444 | return -EIO; |
445 | } | ||
378 | 446 | ||
447 | memcpy(status, buf, len); | ||
448 | kfree(buf); | ||
379 | return 0; | 449 | return 0; |
380 | } | 450 | } |
381 | 451 | ||
@@ -434,6 +504,29 @@ static int enable_oscillator(struct us_data *us) | |||
434 | return 0; | 504 | return 0; |
435 | } | 505 | } |
436 | 506 | ||
507 | static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len) | ||
508 | { | ||
509 | int retval; | ||
510 | u16 addr = 0xFE47; | ||
511 | u8 cmnd[12] = {0}; | ||
512 | |||
513 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __FUNCTION__, addr, len); | ||
514 | |||
515 | cmnd[0] = 0xF0; | ||
516 | cmnd[1] = 0x0E; | ||
517 | cmnd[2] = (u8)(addr >> 8); | ||
518 | cmnd[3] = (u8)addr; | ||
519 | cmnd[4] = (u8)(len >> 8); | ||
520 | cmnd[5] = (u8)len; | ||
521 | |||
522 | retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL); | ||
523 | if (retval != USB_STOR_TRANSPORT_GOOD) { | ||
524 | return -EIO; | ||
525 | } | ||
526 | |||
527 | return 0; | ||
528 | } | ||
529 | |||
437 | static int do_config_autodelink(struct us_data *us, int enable, int force) | 530 | static int do_config_autodelink(struct us_data *us, int enable, int force) |
438 | { | 531 | { |
439 | int retval; | 532 | int retval; |
@@ -454,7 +547,8 @@ static int do_config_autodelink(struct us_data *us, int enable, int force) | |||
454 | 547 | ||
455 | US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value); | 548 | US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value); |
456 | 549 | ||
457 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 550 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
551 | retval = __do_config_autodelink(us, &value, 1); | ||
458 | if (retval < 0) | 552 | if (retval < 0) |
459 | return -EIO; | 553 | return -EIO; |
460 | 554 | ||
@@ -486,7 +580,8 @@ static int config_autodelink_after_power_on(struct us_data *us) | |||
486 | 580 | ||
487 | SET_BIT(value, 7); | 581 | SET_BIT(value, 7); |
488 | 582 | ||
489 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 583 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
584 | retval = __do_config_autodelink(us, &value, 1); | ||
490 | if (retval < 0) | 585 | if (retval < 0) |
491 | return -EIO; | 586 | return -EIO; |
492 | 587 | ||
@@ -507,7 +602,8 @@ static int config_autodelink_after_power_on(struct us_data *us) | |||
507 | CLR_BIT(value, 7); | 602 | CLR_BIT(value, 7); |
508 | } | 603 | } |
509 | 604 | ||
510 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 605 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
606 | retval = __do_config_autodelink(us, &value, 1); | ||
511 | if (retval < 0) | 607 | if (retval < 0) |
512 | return -EIO; | 608 | return -EIO; |
513 | 609 | ||
@@ -584,7 +680,8 @@ static int config_autodelink_before_power_down(struct us_data *us) | |||
584 | if (CHECK_ID(chip, 0x0138, 0x3882)) | 680 | if (CHECK_ID(chip, 0x0138, 0x3882)) |
585 | SET_BIT(value, 2); | 681 | SET_BIT(value, 2); |
586 | 682 | ||
587 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 683 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
684 | retval = __do_config_autodelink(us, &value, 1); | ||
588 | if (retval < 0) | 685 | if (retval < 0) |
589 | return -EIO; | 686 | return -EIO; |
590 | } | 687 | } |
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index e8ae21b2d387..ff32390d61e5 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c | |||
@@ -691,6 +691,9 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
691 | int temp_result; | 691 | int temp_result; |
692 | struct scsi_eh_save ses; | 692 | struct scsi_eh_save ses; |
693 | int sense_size = US_SENSE_SIZE; | 693 | int sense_size = US_SENSE_SIZE; |
694 | struct scsi_sense_hdr sshdr; | ||
695 | const u8 *scdd; | ||
696 | u8 fm_ili; | ||
694 | 697 | ||
695 | /* device supports and needs bigger sense buffer */ | 698 | /* device supports and needs bigger sense buffer */ |
696 | if (us->fflags & US_FL_SANE_SENSE) | 699 | if (us->fflags & US_FL_SANE_SENSE) |
@@ -774,32 +777,30 @@ Retry_Sense: | |||
774 | srb->sense_buffer[7] = (US_SENSE_SIZE - 8); | 777 | srb->sense_buffer[7] = (US_SENSE_SIZE - 8); |
775 | } | 778 | } |
776 | 779 | ||
780 | scsi_normalize_sense(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE, | ||
781 | &sshdr); | ||
782 | |||
777 | US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); | 783 | US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); |
778 | US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", | 784 | US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", |
779 | srb->sense_buffer[0], | 785 | sshdr.response_code, sshdr.sense_key, |
780 | srb->sense_buffer[2] & 0xf, | 786 | sshdr.asc, sshdr.ascq); |
781 | srb->sense_buffer[12], | ||
782 | srb->sense_buffer[13]); | ||
783 | #ifdef CONFIG_USB_STORAGE_DEBUG | 787 | #ifdef CONFIG_USB_STORAGE_DEBUG |
784 | usb_stor_show_sense( | 788 | usb_stor_show_sense(sshdr.sense_key, sshdr.asc, sshdr.ascq); |
785 | srb->sense_buffer[2] & 0xf, | ||
786 | srb->sense_buffer[12], | ||
787 | srb->sense_buffer[13]); | ||
788 | #endif | 789 | #endif |
789 | 790 | ||
790 | /* set the result so the higher layers expect this data */ | 791 | /* set the result so the higher layers expect this data */ |
791 | srb->result = SAM_STAT_CHECK_CONDITION; | 792 | srb->result = SAM_STAT_CHECK_CONDITION; |
792 | 793 | ||
794 | scdd = scsi_sense_desc_find(srb->sense_buffer, | ||
795 | SCSI_SENSE_BUFFERSIZE, 4); | ||
796 | fm_ili = (scdd ? scdd[3] : srb->sense_buffer[2]) & 0xA0; | ||
797 | |||
793 | /* We often get empty sense data. This could indicate that | 798 | /* We often get empty sense data. This could indicate that |
794 | * everything worked or that there was an unspecified | 799 | * everything worked or that there was an unspecified |
795 | * problem. We have to decide which. | 800 | * problem. We have to decide which. |
796 | */ | 801 | */ |
797 | if ( /* Filemark 0, ignore EOM, ILI 0, no sense */ | 802 | if (sshdr.sense_key == 0 && sshdr.asc == 0 && sshdr.ascq == 0 && |
798 | (srb->sense_buffer[2] & 0xaf) == 0 && | 803 | fm_ili == 0) { |
799 | /* No ASC or ASCQ */ | ||
800 | srb->sense_buffer[12] == 0 && | ||
801 | srb->sense_buffer[13] == 0) { | ||
802 | |||
803 | /* If things are really okay, then let's show that. | 804 | /* If things are really okay, then let's show that. |
804 | * Zero out the sense buffer so the higher layers | 805 | * Zero out the sense buffer so the higher layers |
805 | * won't realize we did an unsolicited auto-sense. | 806 | * won't realize we did an unsolicited auto-sense. |
@@ -814,7 +815,10 @@ Retry_Sense: | |||
814 | */ | 815 | */ |
815 | } else { | 816 | } else { |
816 | srb->result = DID_ERROR << 16; | 817 | srb->result = DID_ERROR << 16; |
817 | srb->sense_buffer[2] = HARDWARE_ERROR; | 818 | if ((sshdr.response_code & 0x72) == 0x72) |
819 | srb->sense_buffer[1] = HARDWARE_ERROR; | ||
820 | else | ||
821 | srb->sense_buffer[2] = HARDWARE_ERROR; | ||
818 | } | 822 | } |
819 | } | 823 | } |
820 | } | 824 | } |
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 0ca095820f3e..c325e69415a1 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -831,12 +831,22 @@ static int usb_stor_scan_thread(void * __us) | |||
831 | 831 | ||
832 | dev_dbg(dev, "device found\n"); | 832 | dev_dbg(dev, "device found\n"); |
833 | 833 | ||
834 | set_freezable(); | 834 | set_freezable_with_signal(); |
835 | /* Wait for the timeout to expire or for a disconnect */ | 835 | /* |
836 | * Wait for the timeout to expire or for a disconnect | ||
837 | * | ||
838 | * We can't freeze in this thread or we risk causing khubd to | ||
839 | * fail to freeze, but we can't be non-freezable either. Nor can | ||
840 | * khubd freeze while waiting for scanning to complete as it may | ||
841 | * hold the device lock, causing a hang when suspending devices. | ||
842 | * So we request a fake signal when freezing and use | ||
843 | * interruptible sleep to kick us out of our wait early when | ||
844 | * freezing happens. | ||
845 | */ | ||
836 | if (delay_use > 0) { | 846 | if (delay_use > 0) { |
837 | dev_dbg(dev, "waiting for device to settle " | 847 | dev_dbg(dev, "waiting for device to settle " |
838 | "before scanning\n"); | 848 | "before scanning\n"); |
839 | wait_event_freezable_timeout(us->delay_wait, | 849 | wait_event_interruptible_timeout(us->delay_wait, |
840 | test_bit(US_FLIDX_DONT_SCAN, &us->dflags), | 850 | test_bit(US_FLIDX_DONT_SCAN, &us->dflags), |
841 | delay_use * HZ); | 851 | delay_use * HZ); |
842 | } | 852 | } |