diff options
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
-rw-r--r-- | drivers/scsi/scsi_scan.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index b14dc02c3de..17914a346f7 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/kthread.h> | 33 | #include <linux/kthread.h> |
34 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
35 | #include <linux/async.h> | ||
35 | 36 | ||
36 | #include <scsi/scsi.h> | 37 | #include <scsi/scsi.h> |
37 | #include <scsi/scsi_cmnd.h> | 38 | #include <scsi/scsi_cmnd.h> |
@@ -179,6 +180,8 @@ int scsi_complete_async_scans(void) | |||
179 | spin_unlock(&async_scan_lock); | 180 | spin_unlock(&async_scan_lock); |
180 | 181 | ||
181 | kfree(data); | 182 | kfree(data); |
183 | /* Synchronize async operations globally */ | ||
184 | async_synchronize_full(); | ||
182 | return 0; | 185 | return 0; |
183 | } | 186 | } |
184 | 187 | ||
@@ -216,7 +219,7 @@ static void scsi_unlock_floptical(struct scsi_device *sdev, | |||
216 | scsi_cmd[4] = 0x2a; /* size */ | 219 | scsi_cmd[4] = 0x2a; /* size */ |
217 | scsi_cmd[5] = 0; | 220 | scsi_cmd[5] = 0; |
218 | scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, result, 0x2a, NULL, | 221 | scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, result, 0x2a, NULL, |
219 | SCSI_TIMEOUT, 3); | 222 | SCSI_TIMEOUT, 3, NULL); |
220 | } | 223 | } |
221 | 224 | ||
222 | /** | 225 | /** |
@@ -573,6 +576,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
573 | 576 | ||
574 | /* Each pass gets up to three chances to ignore Unit Attention */ | 577 | /* Each pass gets up to three chances to ignore Unit Attention */ |
575 | for (count = 0; count < 3; ++count) { | 578 | for (count = 0; count < 3; ++count) { |
579 | int resid; | ||
580 | |||
576 | memset(scsi_cmd, 0, 6); | 581 | memset(scsi_cmd, 0, 6); |
577 | scsi_cmd[0] = INQUIRY; | 582 | scsi_cmd[0] = INQUIRY; |
578 | scsi_cmd[4] = (unsigned char) try_inquiry_len; | 583 | scsi_cmd[4] = (unsigned char) try_inquiry_len; |
@@ -581,7 +586,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
581 | 586 | ||
582 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, | 587 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, |
583 | inq_result, try_inquiry_len, &sshdr, | 588 | inq_result, try_inquiry_len, &sshdr, |
584 | HZ / 2 + HZ * scsi_inq_timeout, 3); | 589 | HZ / 2 + HZ * scsi_inq_timeout, 3, |
590 | &resid); | ||
585 | 591 | ||
586 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " | 592 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " |
587 | "with code 0x%x\n", | 593 | "with code 0x%x\n", |
@@ -602,6 +608,14 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
602 | (sshdr.ascq == 0)) | 608 | (sshdr.ascq == 0)) |
603 | continue; | 609 | continue; |
604 | } | 610 | } |
611 | } else { | ||
612 | /* | ||
613 | * if nothing was transferred, we try | ||
614 | * again. It's a workaround for some USB | ||
615 | * devices. | ||
616 | */ | ||
617 | if (resid == try_inquiry_len) | ||
618 | continue; | ||
605 | } | 619 | } |
606 | break; | 620 | break; |
607 | } | 621 | } |
@@ -1390,7 +1404,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, | |||
1390 | 1404 | ||
1391 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, | 1405 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, |
1392 | lun_data, length, &sshdr, | 1406 | lun_data, length, &sshdr, |
1393 | SCSI_TIMEOUT + 4 * HZ, 3); | 1407 | SCSI_TIMEOUT + 4 * HZ, 3, NULL); |
1394 | 1408 | ||
1395 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" | 1409 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" |
1396 | " %s (try %d) result 0x%x\n", result | 1410 | " %s (try %d) result 0x%x\n", result |