diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/scsi.c | 8 | ||||
-rw-r--r-- | drivers/scsi/scsi_scan.c | 10 | ||||
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 12 | ||||
-rw-r--r-- | drivers/usb/storage/usb.c | 8 |
4 files changed, 32 insertions, 6 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index d81f3cc43ff1..1423cb17fbfd 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -670,14 +670,10 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) return SCSI_MLQUEUE_DEVICE_BUSY; } - /* - * If SCSI-2 or lower, store the LUN value in cmnd. - */ - if (cmd->device->scsi_level <= SCSI_2 && - cmd->device->scsi_level != SCSI_UNKNOWN) { + /* Store the LUN value in cmnd, if needed. */ + if (cmd->device->lun_in_cdb) cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) | (cmd->device->lun << 5 & 0xe0); - } scsi_log_send(cmd); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 56675dbbf681..f84c40188478 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -736,6 +736,16 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, sdev->scsi_level++; sdev->sdev_target->scsi_level = sdev->scsi_level; + /* + * If SCSI-2 or lower, and if the transport requires it, + * store the LUN value in CDB[1]. + */ + sdev->lun_in_cdb = 0; + if (sdev->scsi_level <= SCSI_2 && + sdev->scsi_level != SCSI_UNKNOWN && + !sdev->host->no_scsi2_lun_in_cdb) + sdev->lun_in_cdb = 1; + return 0; } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 8b4105a22ac2..85e36f3a5585 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1263,7 +1263,19 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev) sdev->sdev_dev.class = &sdev_class; dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%llu", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); + /* + * Get a default scsi_level from the target (derived from sibling + * devices). This is the best we can do for guessing how to set + * sdev->lun_in_cdb for the initial INQUIRY command. For LUN 0 the + * setting doesn't matter, because all the bits are zero anyway. + * But it does matter for higher LUNs. + */ sdev->scsi_level = starget->scsi_level; + if (sdev->scsi_level <= SCSI_2 && + sdev->scsi_level != SCSI_UNKNOWN && + !shost->no_scsi2_lun_in_cdb) + sdev->lun_in_cdb = 1; + transport_setup_device(&sdev->sdev_gendev); spin_lock_irqsave(shost->host_lock, flags); list_add_tail(&sdev->same_target_siblings, &starget->devices); diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index cedb29252a92..bf3f8e2de046 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -983,6 +983,14 @@ int usb_stor_probe2(struct us_data *us) if (!(us->fflags & US_FL_SCM_MULT_TARG)) us_to_host(us)->max_id = 1; + /* + * Like Windows, we won't store the LUN bits in CDB[1] for SCSI-2 + * devices using the Bulk-Only transport (even though this violates + * the SCSI spec). + */ + if (us->transport == usb_stor_Bulk_transport) + us_to_host(us)->no_scsi2_lun_in_cdb = 1; + /* Find the endpoints and calculate pipe values */ result = get_pipes(us); if (result) |