A number of SCSI drivers currently only see luns #0 in their targets.
This may be a problem when drives have to be assigned bigger lun numbers, e.g. because the storage controllers don't provide enough target numbers to accomodate all drives. (In particular, I'm about to submit a driver for Hyper-V VMBus SCSI controller which is limited to 2 targets only).
This series adds generic SCSI lun enumeration (either via REPORT LUNS command or sequentially trying every lun), and makes the respective drivers use it.
Note that the series has only been minimally tested against a recent QEMU.
Roman Kagan (9): blockcmd: accept only disks and CD-ROMs blockcmd: generic SCSI luns enumeration virtio-scsi: enumerate luns with REPORT LUNS esp-scsi: enumerate luns with REPORT LUNS usb-uas: enumerate luns with REPORT LUNS pvscsi: fix the comment about lun enumeration mpt-scsi: try to enumerate luns with REPORT LUNS lsi-scsi: reset in case of a serious problem lsi-scsi: try to enumerate luns with REPORT LUNS
Signed-off-by: Roman Kagan rkagan@virtuozzo.com --- v1 -> v2: - use malloc_tmp instead of malloc_high - format the retry logic as a regular while{} loop - I left the interface as in v1 as the alternatives looked heavier - patches 1,3-9 are unchanged
src/hw/blockcmd.h | 4 +++ src/hw/blockcmd.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/hw/esp-scsi.c | 35 +++++++++++++------ src/hw/lsi-scsi.c | 39 +++++++++++++++------ src/hw/mpt-scsi.c | 40 ++++++++++++++-------- src/hw/pvscsi.c | 2 +- src/hw/usb-uas.c | 45 +++++++++++++++--------- src/hw/virtio-scsi.c | 38 +++++++++++++------- 8 files changed, 236 insertions(+), 64 deletions(-)
Luns that report to INQUIRY with a type other than CD-ROM are considered disks. This isn't necessarily the case; working with such luns as disks may lead to unpredictable results.
So bail out if the lun is neither CD-ROM nor disk.
Signed-off-by: Roman Kagan rkagan@virtuozzo.com --- src/hw/blockcmd.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/src/hw/blockcmd.c b/src/hw/blockcmd.c index f147100..5ad128e 100644 --- a/src/hw/blockcmd.c +++ b/src/hw/blockcmd.c @@ -217,6 +217,9 @@ scsi_drive_setup(struct drive_s *drive, const char *s, int prio) return 0; }
+ if (pdt != SCSI_TYPE_DISK) + return -1; + ret = scsi_is_ready(&dop); if (ret) { dprintf(1, "scsi_is_ready returned %d\n", ret);
Add two generic functions to discover active LUNs on a SCSI target.
The functions take a temporary drive descriptor on the target, and a callback to create a new drive descriptor with a new LUN using the temporary one as a template.
One of the functions performs REPORT LUNS on the temporary drive to obtain the list of candidate luns; the other sequentially iterates the lun numbers up to the given maximum, and is meant as a fallback. Both functions return the number of successfully created drive descriptors, or a negative number if an error occured.
This will allow to lift the limitation of most of the SCSI drivers that support booting off the LUN #0 only.
Signed-off-by: Roman Kagan rkagan@virtuozzo.com --- v1 -> v2: - use malloc_tmp instead of malloc_high - format the retry logic as a regular while{} loop - I left the interface as in v1 as the alternatives looked heavier
src/hw/blockcmd.h | 4 +++ src/hw/blockcmd.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+)
diff --git a/src/hw/blockcmd.h b/src/hw/blockcmd.h index b543f85..f18543e 100644 --- a/src/hw/blockcmd.h +++ b/src/hw/blockcmd.h @@ -106,5 +106,9 @@ int scsi_is_read(struct disk_op_s *op); int scsi_is_ready(struct disk_op_s *op); struct drive_s; int scsi_drive_setup(struct drive_s *drive, const char *s, int prio); +typedef int (*scsi_add_lun)(u32 lun, struct drive_s *tmpl_drv); +int scsi_rep_luns_scan(struct drive_s *tmp_drive, scsi_add_lun add_lun); +int scsi_sequential_scan(struct drive_s *tmp_drive, u32 maxluns, + scsi_add_lun add_lun);
#endif // blockcmd.h diff --git a/src/hw/blockcmd.c b/src/hw/blockcmd.c index 5ad128e..324188d 100644 --- a/src/hw/blockcmd.c +++ b/src/hw/blockcmd.c @@ -13,6 +13,7 @@ #include "std/disk.h" // DISK_RET_EPARAM #include "string.h" // memset #include "util.h" // timer_calc +#include "malloc.h"
/**************************************************************** @@ -181,6 +182,99 @@ scsi_is_ready(struct disk_op_s *op) return 0; }
+#define CDB_CMD_REPORT_LUNS 0xA0 + +struct cdb_report_luns { + u8 command; + u8 reserved_01[5]; + u32 length; + u8 pad[6]; +} PACKED; + +struct scsi_lun { + u16 lun[4]; +}; + +struct cdbres_report_luns { + u32 length; + u32 reserved; + struct scsi_lun luns[]; +}; + +static u64 scsilun2u64(struct scsi_lun *scsi_lun) +{ + int i; + u64 ret = 0; + for (i = 0; i < ARRAY_SIZE(scsi_lun->lun); i++) + ret |= be16_to_cpu(scsi_lun->lun[i]) << (16 * i); + return ret; +} + +// Issue REPORT LUNS on a temporary drive and iterate reported luns calling +// @add_lun for each +int scsi_rep_luns_scan(struct drive_s *tmp_drive, scsi_add_lun add_lun) +{ + int ret = -1; + u32 maxluns = 511; + u32 nluns, i; + struct cdb_report_luns cdb = { + .command = CDB_CMD_REPORT_LUNS, + }; + struct disk_op_s op = { + .drive_gf = tmp_drive, + .command = CMD_SCSI, + .count = 1, + .cdbcmd = &cdb, + }; + struct cdbres_report_luns *resp; + + ASSERT32FLAT(); + + while (1) { + op.blocksize = sizeof(struct cdbres_report_luns) + + maxluns * sizeof(struct scsi_lun); + op.buf_fl = malloc_tmp(op.blocksize); + if (!op.buf_fl) { + warn_noalloc(); + return -1; + } + + cdb.length = cpu_to_be32(op.blocksize); + if (process_op(&op) != DISK_RET_SUCCESS) + goto out; + + resp = op.buf_fl; + nluns = be32_to_cpu(resp->length) / sizeof(struct scsi_lun); + if (nluns <= maxluns) + break; + + free(op.buf_fl); + maxluns = nluns; + } + + for (i = 0, ret = 0; i < nluns; i++) { + u64 lun = scsilun2u64(&resp->luns[i]); + if (lun >> 32) + continue; + ret += !add_lun((u32)lun, tmp_drive); + } +out: + free(op.buf_fl); + return ret; +} + +// Iterate LUNs on the target and call @add_lun for each +int scsi_sequential_scan(struct drive_s *tmp_drive, u32 maxluns, + scsi_add_lun add_lun) +{ + int ret; + u32 lun; + + for (lun = 0, ret = 0; lun < maxluns; lun++) + ret += !add_lun(lun, tmp_drive); + return ret; +} + // Validate drive, find block size / sector count, and register drive. int scsi_drive_setup(struct drive_s *drive, const char *s, int prio)
Signed-off-by: Roman Kagan rkagan@virtuozzo.com --- src/hw/virtio-scsi.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-)
diff --git a/src/hw/virtio-scsi.c b/src/hw/virtio-scsi.c index 5fb9409..7490ec0 100644 --- a/src/hw/virtio-scsi.c +++ b/src/hw/virtio-scsi.c @@ -94,15 +94,11 @@ virtio_scsi_process_op(struct disk_op_s *op) return DISK_RET_EBADTRACK; }
-static int -virtio_scsi_add_lun(struct pci_device *pci, struct vp_device *vp, - struct vring_virtqueue *vq, u16 target, u16 lun) +static void +virtio_scsi_init_lun(struct virtio_lun_s *vlun, struct pci_device *pci, + struct vp_device *vp, struct vring_virtqueue *vq, + u16 target, u16 lun) { - struct virtio_lun_s *vlun = malloc_fseg(sizeof(*vlun)); - if (!vlun) { - warn_noalloc(); - return -1; - } memset(vlun, 0, sizeof(*vlun)); vlun->drive.type = DTYPE_VIRTIO_SCSI; vlun->drive.cntl_id = pci->bdf; @@ -111,8 +107,22 @@ virtio_scsi_add_lun(struct pci_device *pci, struct vp_device *vp, vlun->vq = vq; vlun->target = target; vlun->lun = lun; +}
- int prio = bootprio_find_scsi_device(pci, target, lun); +static int +virtio_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) +{ + struct virtio_lun_s *tmpl_vlun = + container_of(tmpl_drv, struct virtio_lun_s, drive); + struct virtio_lun_s *vlun = malloc_fseg(sizeof(*vlun)); + if (!vlun) { + warn_noalloc(); + return -1; + } + virtio_scsi_init_lun(vlun, tmpl_vlun->pci, tmpl_vlun->vp, tmpl_vlun->vq, + tmpl_vlun->target, lun); + + int prio = bootprio_find_scsi_device(vlun->pci, vlun->target, vlun->lun); int ret = scsi_drive_setup(&vlun->drive, "virtio-scsi", prio); if (ret) goto fail; @@ -127,9 +137,13 @@ static int virtio_scsi_scan_target(struct pci_device *pci, struct vp_device *vp, struct vring_virtqueue *vq, u16 target) { - /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ - int ret = virtio_scsi_add_lun(pci, vp, vq, target, 0); - return ret < 0 ? 0 : 1; + + struct virtio_lun_s vlun0; + + virtio_scsi_init_lun(&vlun0, pci, vp, vq, target, 0); + + int ret = scsi_rep_luns_scan(&vlun0.drive, virtio_scsi_add_lun); + return ret < 0 ? 0 : ret; }
static void
Signed-off-by: Roman Kagan rkagan@virtuozzo.com --- src/hw/esp-scsi.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-)
diff --git a/src/hw/esp-scsi.c b/src/hw/esp-scsi.c index d2ba023..57d3832 100644 --- a/src/hw/esp-scsi.c +++ b/src/hw/esp-scsi.c @@ -153,14 +153,10 @@ esp_scsi_process_op(struct disk_op_s *op) return DISK_RET_EBADTRACK; }
-static int -esp_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) +static void +esp_scsi_init_lun(struct esp_lun_s *llun, struct pci_device *pci, u32 iobase, + u8 target, u8 lun) { - struct esp_lun_s *llun = malloc_fseg(sizeof(*llun)); - if (!llun) { - warn_noalloc(); - return -1; - } memset(llun, 0, sizeof(*llun)); llun->drive.type = DTYPE_ESP_SCSI; llun->drive.cntl_id = pci->bdf; @@ -168,9 +164,24 @@ esp_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) llun->target = target; llun->lun = lun; llun->iobase = iobase; +} + +static int +esp_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) +{ + struct esp_lun_s *tmpl_llun = + container_of(tmpl_drv, struct esp_lun_s, drive); + struct esp_lun_s *llun = malloc_fseg(sizeof(*llun)); + if (!llun) { + warn_noalloc(); + return -1; + } + esp_scsi_init_lun(llun, tmpl_llun->pci, tmpl_llun->iobase, + tmpl_llun->target, lun);
- char *name = znprintf(MAXDESCSIZE, "esp %pP %d:%d", pci, target, lun); - int prio = bootprio_find_scsi_device(pci, target, lun); + char *name = znprintf(MAXDESCSIZE, "esp %pP %d:%d", + llun->pci, llun->target, llun->lun); + int prio = bootprio_find_scsi_device(llun->pci, llun->target, llun->lun); int ret = scsi_drive_setup(&llun->drive, name, prio); free(name); if (ret) @@ -185,7 +196,11 @@ fail: static void esp_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target) { - esp_scsi_add_lun(pci, iobase, target, 0); + struct esp_lun_s llun0; + + esp_scsi_init_lun(&llun0, pci, iobase, target, 0); + + scsi_rep_luns_scan(&llun0.drive, esp_scsi_add_lun); }
static void
Signed-off-by: Roman Kagan rkagan@virtuozzo.com --- src/hw/usb-uas.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-)
diff --git a/src/hw/usb-uas.c b/src/hw/usb-uas.c index 10e3845..f00221a 100644 --- a/src/hw/usb-uas.c +++ b/src/hw/usb-uas.c @@ -86,8 +86,9 @@ typedef struct {
struct uasdrive_s { struct drive_s drive; + struct usbdevice_s *usbdev; struct usb_pipe *command, *status, *data_in, *data_out; - int lun; + u32 lun; };
int @@ -168,30 +169,41 @@ fail: return DISK_RET_EBADTRACK; }
-static int -uas_lun_setup(struct usbdevice_s *usbdev, - struct usb_pipe *command, struct usb_pipe *status, - struct usb_pipe *data_in, struct usb_pipe *data_out, - int lun) +static void +uas_init_lun(struct uasdrive_s *drive, struct usbdevice_s *usbdev, + struct usb_pipe *command, struct usb_pipe *status, + struct usb_pipe *data_in, struct usb_pipe *data_out, + u32 lun) { - // Allocate drive structure. - struct uasdrive_s *drive = malloc_fseg(sizeof(*drive)); - if (!drive) { - warn_noalloc(); - return -1; - } memset(drive, 0, sizeof(*drive)); if (usb_32bit_pipe(data_in)) drive->drive.type = DTYPE_UAS_32; else drive->drive.type = DTYPE_UAS; + drive->usbdev = usbdev; drive->command = command; drive->status = status; drive->data_in = data_in; drive->data_out = data_out; drive->lun = lun; +} + +static int +uas_add_lun(u32 lun, struct drive_s *tmpl_drv) +{ + struct uasdrive_s *tmpl_lun = + container_of(tmpl_drv, struct uasdrive_s, drive); + struct uasdrive_s *drive = malloc_fseg(sizeof(*drive)); + if (!drive) { + warn_noalloc(); + return -1; + } + uas_init_lun(drive, tmpl_lun->usbdev, + tmpl_lun->command, tmpl_lun->status, + tmpl_lun->data_in, tmpl_lun->data_out, + lun);
- int prio = bootprio_find_usb(usbdev, lun); + int prio = bootprio_find_usb(drive->usbdev, drive->lun); int ret = scsi_drive_setup(&drive->drive, "USB UAS", prio); if (ret) { free(drive); @@ -258,9 +270,10 @@ usb_uas_setup(struct usbdevice_s *usbdev) if (!command || !status || !data_in || !data_out) goto fail;
- /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ - int ret = uas_lun_setup(usbdev, command, status, data_in, data_out, 0); - if (ret < 0) { + struct uasdrive_s lun0; + uas_init_lun(&lun0, usbdev, command, status, data_in, data_out, 0); + int ret = scsi_rep_luns_scan(&lun0.drive, uas_add_lun); + if (ret <= 0) { dprintf(1, "Unable to configure UAS drive.\n"); goto fail; }
The comment in pvscsi_scan_target (presumably c&p-ed from another driver) reads that REPORTS LUNS should better be used to enumerate the luns on the target.
However, according to the Linux driver, the device supports no more than a single lun per target.
So adjust the comment to tell exactly that.
Signed-off-by: Roman Kagan rkagan@virtuozzo.com --- src/hw/pvscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/hw/pvscsi.c b/src/hw/pvscsi.c index cd4046c..7c850a9 100644 --- a/src/hw/pvscsi.c +++ b/src/hw/pvscsi.c @@ -290,7 +290,7 @@ static void pvscsi_scan_target(struct pci_device *pci, void *iobase, struct pvscsi_ring_dsc_s *ring_dsc, u8 target) { - /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ + /* pvscsi has no more than a single lun per target */ pvscsi_add_lun(pci, iobase, ring_dsc, target, 0); }
Enumerate active luns with REPORT LUNS and, if that fails[*], fall back to sequentially enumerating them up to (arbitrarily chosen) #8.
Note that this patch also makes mpt_scsi_cmd accept luns other than 0; I've no idea what was the original motivation not to, and what can break due to this change (nothing broke in my basic tests with QEMU).
[*] in current QEMU, REPORT LUNS does fail in mptsas1068 because the returned data is smaller than the allocation length which is (wrongly) considered an underflow.
Signed-off-by: Roman Kagan rkagan@virtuozzo.com --- src/hw/mpt-scsi.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-)
diff --git a/src/hw/mpt-scsi.c b/src/hw/mpt-scsi.c index a37e44c..7bc8a85 100644 --- a/src/hw/mpt-scsi.c +++ b/src/hw/mpt-scsi.c @@ -118,9 +118,6 @@ static int mpt_scsi_cmd(u32 iobase, struct disk_op_s *op, u8 *cdb, u16 target, u16 lun, u16 blocksize) { - if (lun != 0) - return DISK_RET_ENOTREADY; - u32 end = timer_calc(MPT_POLL_TIMEOUT);
u8 sense_buf[18]; @@ -198,14 +195,10 @@ mpt_scsi_process_op(struct disk_op_s *op) return mpt_scsi_cmd(iobase, op, cdbcmd, target, lun, blocksize); }
-static int -mpt_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) +static void +mpt_scsi_init_lun(struct mpt_lun_s *llun, struct pci_device *pci, + u32 iobase, u8 target, u8 lun) { - struct mpt_lun_s *llun = malloc_fseg(sizeof(*llun)); - if (!llun) { - warn_noalloc(); - return -1; - } memset(llun, 0, sizeof(*llun)); llun->drive.type = DTYPE_MPT_SCSI; llun->drive.cntl_id = pci->bdf; @@ -213,9 +206,24 @@ mpt_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) llun->target = target; llun->lun = lun; llun->iobase = iobase; +}
- char *name = znprintf(MAXDESCSIZE, "mpt %pP %d:%d", pci, target, lun); - int prio = bootprio_find_scsi_device(pci, target, lun); +static int +mpt_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) +{ + struct mpt_lun_s *tmpl_llun = + container_of(tmpl_drv, struct mpt_lun_s, drive); + struct mpt_lun_s *llun = malloc_fseg(sizeof(*llun)); + if (!llun) { + warn_noalloc(); + return -1; + } + mpt_scsi_init_lun(llun, tmpl_llun->pci, tmpl_llun->iobase, + tmpl_llun->target, lun); + + char *name = znprintf(MAXDESCSIZE, "mpt %pP %d:%d", + llun->pci, llun->target, llun->lun); + int prio = bootprio_find_scsi_device(llun->pci, llun->target, llun->lun); int ret = scsi_drive_setup(&llun->drive, name, prio); free(name); if (ret) { @@ -231,8 +239,12 @@ fail: static void mpt_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target) { - /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ - mpt_scsi_add_lun(pci, iobase, target, 0); + struct mpt_lun_s llun0; + + mpt_scsi_init_lun(&llun0, pci, iobase, target, 0); + + if (scsi_rep_luns_scan(&llun0.drive, mpt_scsi_add_lun) < 0) + scsi_sequential_scan(&llun0.drive, 8, mpt_scsi_add_lun); }
static inline void
When the device reports a serious problem via SIST[01] registers, it needs to be reset, otherwise the following requests will most likely fail, too.
In particular, REPORT LUNS which fails (wrongly) with underflow in QEMU makes all the following requests fail, too, rendering the device unusable.
Signed-off-by: Roman Kagan rkagan@virtuozzo.com --- src/hw/lsi-scsi.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/src/hw/lsi-scsi.c b/src/hw/lsi-scsi.c index b63430d..d264993 100644 --- a/src/hw/lsi-scsi.c +++ b/src/hw/lsi-scsi.c @@ -116,6 +116,8 @@ lsi_scsi_process_op(struct disk_op_s *op) u8 sist0 = inb(iobase + LSI_REG_SIST0); u8 sist1 = inb(iobase + LSI_REG_SIST1); if (sist0 || sist1) { + /* serious problem, can't continue w/o reset */ + outb(LSI_ISTAT0_SRST, iobase + LSI_REG_ISTAT0); goto fail; } if (dstat & 0x04) {
Enumerate active luns with REPORT LUNS and, if that fails[*], fall back to sequentially enumerating them up to (arbitrarily chosen) #8 [**].
[*] in current QEMU, REPORT LUNS does fail in lsi53c895a because the returned data is smaller than the allocation length which is (wrongly) considered an underflow
[**] in current QEMU, luns above 0 are not supported in lsi53c895a, so this patch is here only for completeness.
Signed-off-by: Roman Kagan rkagan@virtuozzo.com --- src/hw/lsi-scsi.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-)
diff --git a/src/hw/lsi-scsi.c b/src/hw/lsi-scsi.c index d264993..846bb0b 100644 --- a/src/hw/lsi-scsi.c +++ b/src/hw/lsi-scsi.c @@ -134,14 +134,10 @@ fail: return DISK_RET_EBADTRACK; }
-static int -lsi_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) +static void +lsi_scsi_init_lun(struct lsi_lun_s *llun, struct pci_device *pci, u32 iobase, + u8 target, u8 lun) { - struct lsi_lun_s *llun = malloc_fseg(sizeof(*llun)); - if (!llun) { - warn_noalloc(); - return -1; - } memset(llun, 0, sizeof(*llun)); llun->drive.type = DTYPE_LSI_SCSI; llun->drive.cntl_id = pci->bdf; @@ -149,9 +145,24 @@ lsi_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) llun->target = target; llun->lun = lun; llun->iobase = iobase; +} + +static int +lsi_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) +{ + struct lsi_lun_s *tmpl_llun = + container_of(tmpl_drv, struct lsi_lun_s, drive); + struct lsi_lun_s *llun = malloc_fseg(sizeof(*llun)); + if (!llun) { + warn_noalloc(); + return -1; + } + lsi_scsi_init_lun(llun, tmpl_llun->pci, tmpl_llun->iobase, + tmpl_llun->target, lun);
- char *name = znprintf(MAXDESCSIZE, "lsi %pP %d:%d", pci, target, lun); - int prio = bootprio_find_scsi_device(pci, target, lun); + char *name = znprintf(MAXDESCSIZE, "lsi %pP %d:%d", + llun->pci, llun->target, llun->lun); + int prio = bootprio_find_scsi_device(llun->pci, llun->target, llun->lun); int ret = scsi_drive_setup(&llun->drive, name, prio); free(name); if (ret) @@ -166,8 +177,12 @@ fail: static void lsi_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target) { - /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */ - lsi_scsi_add_lun(pci, iobase, target, 0); + struct lsi_lun_s llun0; + + lsi_scsi_init_lun(&llun0, pci, iobase, target, 0); + + if (scsi_rep_luns_scan(&llun0.drive, lsi_scsi_add_lun) < 0) + scsi_sequential_scan(&llun0.drive, 8, lsi_scsi_add_lun); }
static void
On Wed, Apr 26, 2017 at 05:18:00PM +0300, Roman Kagan wrote:
A number of SCSI drivers currently only see luns #0 in their targets.
This may be a problem when drives have to be assigned bigger lun numbers, e.g. because the storage controllers don't provide enough target numbers to accomodate all drives. (In particular, I'm about to submit a driver for Hyper-V VMBus SCSI controller which is limited to 2 targets only).
This series adds generic SCSI lun enumeration (either via REPORT LUNS command or sequentially trying every lun), and makes the respective drivers use it.
Thanks. I committed this series.
-Kevin