@@ -802,6 +802,14 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
} else {
sdev->type = (inq_result[0] & 0x1f);
sdev->removable = (inq_result[1] & 0x80) >> 7;
+
+ /*
+ * some devices may respond with wrong type for
+ * well-known logical units. Force well-known type
+ * to enumerate them correctly.
+ */
+ if (scsi_is_wlun(sdev->lun) && (sdev->type != TYPE_WLUN))
+ sdev->type = TYPE_WLUN;
}
switch (sdev->type) {
@@ -817,6 +825,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
case TYPE_COMM:
case TYPE_RAID:
case TYPE_OSD:
+ case TYPE_WLUN:
sdev->writeable = 1;
break;
case TYPE_ROM:
@@ -1412,6 +1421,13 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
*/
memset(&scsi_cmd[1], 0, 5);
+ if (shost->report_wlus)
+ /*
+ * Set "SELECT REPORT" field to 0x2 which will make device to
+ * report well known logical units along with standard LUs.
+ */
+ scsi_cmd[2] = 0x2;
+
/*
* bytes 6 - 9: length of the command.
*/
@@ -1060,6 +1060,13 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
}
}
+ /*
+ * put runtime pm reference for well-known logical units,
+ * drivers are expected to _get_* again during probe.
+ */
+ if (scsi_is_wlun(sdev->lun))
+ scsi_autopm_put_device(sdev);
+
return error;
}
@@ -332,6 +332,7 @@ static inline int scsi_status_is_good(int status)
#define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */
#define TYPE_RBC 0x0e
#define TYPE_OSD 0x11
+#define TYPE_WLUN 0x1e /* well-known logical unit */
#define TYPE_NO_LUN 0x7f
/* SCSI protocols; these are taken from SPC-3 section 7.5 */
@@ -675,6 +675,11 @@ struct Scsi_Host {
unsigned no_write_same:1;
/*
+ * Set "SELECT REPORT" field to allow detection of well known logical
+ * units along with standard LUs.
+ */
+ unsigned report_wlus:1;
+ /*
* Optional work queue to be utilized by the transport
*/
char work_q_name[20];