Discussion:
Multiple LUNs not detected with SCM USB-SCSI converter
Mark Knibbs
2014-10-08 17:13:13 UTC
Permalink
Hi,

SCM-based USB-SCSI converters work with multi-LUN devices. I tested an MPL
MCDISK-D dual PCMCIA SCSI device in a Windows XP VM (with SCM driver
installed). Windows detected cards in both slots and added drive letters
for them.

With Linux however, only the lower slot (LUN 0) is detected. It seems the
us->max_lun field is zero for SCM converters.

SCM converters use the US_FL_SCM_MULT_TARG quirk. I first thought the
problem might be this code in usb_stor_scan_dwork():

/* For bulk-only devices, determine the max LUN value */
if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
mutex_lock(&us->dev_mutex);
us->max_lun = usb_stor_Bulk_max_lun(us);
mutex_unlock(&us->dev_mutex);
}
scsi_scan_host(us_to_host(us));

usb_stor_Bulk_max_lun() returns 0 for an SCM converter; with usb-storage
debugging enabled, I see this in the log:
GetMaxLUN command result is -32, data is 0

So us->max_lun gets set to 0 which is presumably why LUNs > 0 are not
scanned. I tried changing the above code to

/* For bulk-only devices, determine the max LUN value */
if (us->protocol == USB_PR_BULK &&
!(us->fflags & (US_FL_SINGLE_LUN | US_FL_SCM_MULT_TARG))) {
mutex_lock(&us->dev_mutex);
...

But that change alone didn't seem to make any difference; with USB
debugging enabled I got this log output:
[ 205.823597] *** thread awakened
[ 205.823605] Command INQUIRY (6 bytes)
[ 205.823607] bytes:
[ 205.823608] 12 00 00 00 24 00
[ 205.823620] Bulk Command S 0x43425355 T 0x12 L 36 F 128 Trg 3 LUN 0 CL 6
[ 205.823622] xfer 31 bytes
[ 205.824455] Status code 0; transferred 31/31
[ 205.824459] -- transfer complete
[ 205.824462] Bulk command transfer result=0
[ 205.824466] xfer 36 bytes, 1 entries
[ 205.841459] Status code 0; transferred 36/36
[ 205.841463] -- transfer complete
[ 205.841466] Bulk data transfer result 0x0
[ 205.841469] Attempting to get CSW...
[ 205.841473] xfer 13 bytes
[ 205.843450] Status code 0; transferred 13/13
[ 205.843454] -- transfer complete
[ 205.843458] Bulk status result = 0
[ 205.843462] Bulk Status S 0x53425355 T 0x12 R 0 Stat 0x0
[ 205.843466] scsi cmd done, result=0x0
[ 205.843471] *** thread sleeping
[ 205.843521] scsi 7:0:3:0: Direct-Access MPL MC-DISK-D-1S[0] 3.3 PQ: 0 ANSI: 2
[ 205.843581] *** thread awakened
[ 205.843585] Bad LUN (3:1)
[ 205.843589] scsi cmd done, result=0x40000
[ 205.843594] *** thread sleeping
[ 205.843654] *** thread awakened
[ 205.843657] Command INQUIRY (6 bytes)
[ 205.843659] bytes:
[ 205.843660] 12 00 00 00 24 00
[ 205.843666] Bulk Command S 0x43425355 T 0x13 L 36 F 128 Trg 4 LUN 0 CL 6
[ 205.843668] xfer 31 bytes

Note the Bad LUN message. That's produced by this code in
usb_stor_control_thread():

else if (us->srb->device->lun > us->max_lun) {
usb_stor_dbg(us, "Bad LUN (%d:%llu)\n",
us->srb->device->id,
us->srb->device->lun);
us->srb->result = DID_BAD_TARGET << 16;
}

So at that point, us->max_lun must be zero. What is us->max_lun initially
set to?

usb_stor_probe1() calls get_transport() then get_protocol().
get_transport() looks like this:

/* Get the transport settings */
static void get_transport(struct us_data *us)
{
switch (us->protocol) {
case USB_PR_CB:
us->transport_name = "Control/Bulk";
us->transport = usb_stor_CB_transport;
us->transport_reset = usb_stor_CB_reset;
us->max_lun = 7;
break;

case USB_PR_CBI:
us->transport_name = "Control/Bulk/Interrupt";
us->transport = usb_stor_CB_transport;
us->transport_reset = usb_stor_CB_reset;
us->max_lun = 7;
break;

case USB_PR_BULK:
us->transport_name = "Bulk";
us->transport = usb_stor_Bulk_transport;
us->transport_reset = usb_stor_Bulk_reset;
break;
}
}

us->max_lun isn't set to 7 in the USB_PR_BULK case. Should it be?

get_protocol() looks like this:
/* Get the protocol settings */
static void get_protocol(struct us_data *us)
{
switch (us->subclass) {
case USB_SC_RBC:
us->protocol_name = "Reduced Block Commands (RBC)";
us->proto_handler = usb_stor_transparent_scsi_command;
break;

case USB_SC_8020:
us->protocol_name = "8020i";
us->proto_handler = usb_stor_pad12_command;
us->max_lun = 0;
break;

case USB_SC_QIC:
us->protocol_name = "QIC-157";
us->proto_handler = usb_stor_pad12_command;
us->max_lun = 0;
break;

case USB_SC_8070:
us->protocol_name = "8070i";
us->proto_handler = usb_stor_pad12_command;
us->max_lun = 0;
break;

case USB_SC_SCSI:
us->protocol_name = "Transparent SCSI";
us->proto_handler = usb_stor_transparent_scsi_command;
break;

case USB_SC_UFI:
us->protocol_name = "Uniform Floppy Interface (UFI)";
us->proto_handler = usb_stor_ufi_command;
break;
}
}

max_lun isn't set for the USB_SC_SCSI case (which the SCM converters use).

I can think of several ways to fix this, and would like some input on which
is the best/neatest:

1. Change usb_stor_Bulk_max_lun() to return 7 in the US_FL_SCM_MULT_TARG
case (don't issue Get Max LUN to the USB device).

2. In usb_stor_scan_dwork(), don't call usb_stor_Bulk_max_lun() in the
US_FL_SCM_MULT_TARG case, and one of:
(a) In usb_stor_probe2(), set us->max_lun to 7 in the
US_FL_SCM_MULT_TARG case
(b) In get_transport(), set us->max_lun to 7 in the USB_PR_BULK case
(c) In get_protocol(), set us->max_lun to 7 in the USB_SC_SCSI case

I compiled a kernel with option 2+(a) and it does detect LUNs > 0; here's
part of lsscsi output with the modified kernel:

[9:0:0:0]optical HP C1113M 1.19 /dev/sdg /dev/sg7
[9:0:3:0]disk MPL MC-DISK-D-1S[0] 3.3 /dev/sdh /dev/sg8
[9:0:3:1]disk MPL MC-DISK-D-1S[0] 3.3 - /dev/sg9
[9:0:3:2]disk MPL MC-DISK-D-1S[1] 3.3 - /dev/sg10
[9:0:3:3]disk MPL MC-DISK-D-1S[1] 3.3 /dev/sdi /dev/sg11
[9:0:3:4]disk MPL MC-DISK-D-1S[1] 3.3 /dev/sdj /dev/sg12
[9:0:3:5]disk MPL MC-DISK-D-1S[1] 3.3 /dev/sdk /dev/sg13
[9:0:3:6]disk MPL MC-DISK-D-1S[0] 3.3 /dev/sdl /dev/sg14
[9:0:3:7]disk MPL MC-DISK-D-1S[0] 3.3 /dev/sdm /dev/sg15

Could any other multiple-LUN-supporting devices be affected by this issue?
Perhaps option 2+(c) might be better if so?

[Also, looking at get_protocol(), should max_lun be set to 0 for the
US_SC_RBC case?]


Mark
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Alan Stern
2014-10-08 20:13:22 UTC
Permalink
Post by Mark Knibbs
Hi,
SCM-based USB-SCSI converters work with multi-LUN devices. I tested an MPL
MCDISK-D dual PCMCIA SCSI device in a Windows XP VM (with SCM driver
installed). Windows detected cards in both slots and added drive letters
for them.
With Linux however, only the lower slot (LUN 0) is detected. It seems the
us->max_lun field is zero for SCM converters.
...
Post by Mark Knibbs
I can think of several ways to fix this, and would like some input on which
1. Change usb_stor_Bulk_max_lun() to return 7 in the US_FL_SCM_MULT_TARG
case (don't issue Get Max LUN to the USB device).
2. In usb_stor_scan_dwork(), don't call usb_stor_Bulk_max_lun() in the
(a) In usb_stor_probe2(), set us->max_lun to 7 in the
US_FL_SCM_MULT_TARG case
(b) In get_transport(), set us->max_lun to 7 in the USB_PR_BULK case
(c) In get_protocol(), set us->max_lun to 7 in the USB_SC_SCSI case
Either way, usb_stor_Bulk_max_lun() shouldn't do anything for
SCM_MULT_TARG devices. Indeed, the value would be meaningless because
each target can have a different number of logical units.

Since it isn't going to do anything for those devices, you might as
well avoid calling it, which means using approach 2. But instead of a,
b, or c, just do something simple like this in usb_stor_scan_dworkd():

/* For bulk-only devices, determine the max LUN value */
if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
if (us->fflags & US_FL_SCM_MULT_TARG) {
/*
* Multiple-target devices can have different numbers
* of LUNs on different targets. We will allow all
* of them to be probed.
*/
us->max_lun = 7;
} else {
mutex_lock(&us->dev_mutex);
us->max_lun = usb_stor_Bulk_max_lun(us);
mutex_unlock(&us->dev_mutex);
}
}

Do you know that all SCM_MULT_TARG devices use the Bulk-only transport?
Post by Mark Knibbs
I compiled a kernel with option 2+(a) and it does detect LUNs > 0; here's
[9:0:0:0]optical HP C1113M 1.19 /dev/sdg /dev/sg7
[9:0:3:0]disk MPL MC-DISK-D-1S[0] 3.3 /dev/sdh /dev/sg8
[9:0:3:1]disk MPL MC-DISK-D-1S[0] 3.3 - /dev/sg9
[9:0:3:2]disk MPL MC-DISK-D-1S[1] 3.3 - /dev/sg10
[9:0:3:3]disk MPL MC-DISK-D-1S[1] 3.3 /dev/sdi /dev/sg11
[9:0:3:4]disk MPL MC-DISK-D-1S[1] 3.3 /dev/sdj /dev/sg12
[9:0:3:5]disk MPL MC-DISK-D-1S[1] 3.3 /dev/sdk /dev/sg13
[9:0:3:6]disk MPL MC-DISK-D-1S[0] 3.3 /dev/sdl /dev/sg14
[9:0:3:7]disk MPL MC-DISK-D-1S[0] 3.3 /dev/sdm /dev/sg15
Could any other multiple-LUN-supporting devices be affected by this issue?
Every multiple-target USB device will be affected.
Post by Mark Knibbs
Perhaps option 2+(c) might be better if so?
[Also, looking at get_protocol(), should max_lun be set to 0 for the
US_SC_RBC case?]
Explicitly setting max_lun to 0 may be useful for documentation
purposes but it isn't really necessary, because the entire structure is
initialized to 0 when it is allocated. I don't know why three of the
cases bother to do it. Maybe the specifications for those protocols
forbid multiple LUNs.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Mark Knibbs
2014-10-09 20:41:12 UTC
Permalink
Hi,

On Wed, 8 Oct 2014 16:13:22 -0400 (EDT)
Post by Alan Stern
Post by Mark Knibbs
SCM-based USB-SCSI converters work with multi-LUN devices. I tested an MPL
...
With Linux however, only the lower slot (LUN 0) is detected. It seems the
us->max_lun field is zero for SCM converters.
...
Post by Mark Knibbs
I can think of several ways to fix this, and would like some input on which
1. Change usb_stor_Bulk_max_lun() to return 7 in the US_FL_SCM_MULT_TARG
case (don't issue Get Max LUN to the USB device).
2. In usb_stor_scan_dwork(), don't call usb_stor_Bulk_max_lun() in the
(a) In usb_stor_probe2(), set us->max_lun to 7 in the
US_FL_SCM_MULT_TARG case
(b) In get_transport(), set us->max_lun to 7 in the USB_PR_BULK case
(c) In get_protocol(), set us->max_lun to 7 in the USB_SC_SCSI case
Either way, usb_stor_Bulk_max_lun() shouldn't do anything for
SCM_MULT_TARG devices. Indeed, the value would be meaningless because
each target can have a different number of logical units.
Since it isn't going to do anything for those devices, you might as
well avoid calling it, which means using approach 2. But instead of a,
/* For bulk-only devices, determine the max LUN value */
if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
if (us->fflags & US_FL_SCM_MULT_TARG) {
/*
* Multiple-target devices can have different numbers
* of LUNs on different targets. We will allow all
* of them to be probed.
*/
us->max_lun = 7;
} else {
mutex_lock(&us->dev_mutex);
us->max_lun = usb_stor_Bulk_max_lun(us);
mutex_unlock(&us->dev_mutex);
}
}
Since setting max_lun to 0 in the US_FL_SINGLE_LUN case is done elsewhere,
how about setting max_lun to 7 for US_FL_SCM_MULT_TARG next to that? So the
above could could become:

/*
* Determine the max LUN value for bulk-only devices, except in
* the US_FL_SINGLE_LUN and US_FL_SCM_MULT_TARG cases where max_lun
* is set by usb_stor_probe2().
*/
if (us->protocol == USB_PR_BULK &&
!(us->fflags & (US_FL_SINGLE_LUN | US_FL_SCM_MULT_TARG))) {
mutex_lock(&us->dev_mutex);
us->max_lun = usb_stor_Bulk_max_lun(us);
mutex_unlock(&us->dev_mutex);
}

Then in usb_stor_probe2():
/* fix for single-lun devices */
if (us->fflags & US_FL_SINGLE_LUN) {
us->max_lun = 0;
} else if (us->fflags & US_FL_SCM_MULT_TARG) {
/*
* Multiple-target devices can have different numbers of
* LUNs on different targets. Allow all to be probed.
*/
us->max_lun = 7;
}

That would also work if us->protocol != USB_PR_BULK.
Post by Alan Stern
Do you know that all SCM_MULT_TARG devices use the Bulk-only transport?
Good question. It seems SCM converters support bulk-only and "CBC" (CBI
with no command completion interrupt?); there's a comment in the Windows
driver .INF file:
; DriverFlags field bitmap definition
; ...
; 0x00000010 => Force CBC Protocol
; 0x00000020 => Force BONLY Protocol

An extract from lsusb -v output for a Belkin F5U015:
bInterfaceClass 8 Mass Storage
bInterfaceSubClass 6 SCSI
bInterfaceProtocol 80 Bulk (Zip)
iInterface 4 BONLY and CBC Interface

Three entries for SCM-based converters in unusual-devs.h have USB_SC_SCSI,
USB_PR_BULK though (as opposed to USB_SC_DEVICE, USB_PR_DEVICE): 04E6:000B,
04E6:000C, and 050D:0115. I don't have any of those so can't say whether
USB_SC_SCSI/USB_PR_BULK is necessary for those quirk entries.

So the answer to your question is probably yes. But it might be better to
not rely on that.

In get_transport() there is:

switch (us->protocol) {
case USB_PR_CB:
us->transport_name = "Control/Bulk";
us->transport = usb_stor_CB_transport;
us->transport_reset = usb_stor_CB_reset;
us->max_lun = 7;
break;

Could a hacky way to get an SCM converter to work with multiple LUNs be to
just change its useProtocol UNUSUAL_DEV entry to USB_PR_CB? That should
force the kernel to use control/bulk protocol, and thus set max_lun to 7
with no other code change.

By the way: is there any technical advantage to bulk-only vs control/bulk
protocol?

To digress slightly, I just built a kernel with USB_PR_CB instead of
USB_PR_DEVICE for the SCM converter quirk. A couple of points on testing
that:

- Throughput is faster with CB than bulk-only. Using sg_rbuf to issue
512KB READ BUFFER commands gives 865,160 bytes/sec with bulk-only but
917,865 with CB; about 6% faster. Smaller transfer sizes have a much
greater difference; CB was 100% faster for 1KB transfer size (BOT 128000,
CB 256000) and 33% faster for 8KB transfers (BOT 511996, CB 682667). Does
the CB protocol have less command overhead?

- I had one single-LUN drive connected, but 8 block devices were created
(one for each LUN). With the bulk-only protocol but max_lun set to 7,
there were no bogus/phantom drives. I wonder if the SCM converters, when
using Control/Bulk protocol, need target/LUN information in one of the
reserved bytes of the ADSC setup packet (bytes 2, 3 or 5)...
Post by Alan Stern
Post by Mark Knibbs
Could any other multiple-LUN-supporting devices be affected by this issue?
Every multiple-target USB device will be affected.
Right. Are there any others, other than USB-SCSI converters?

Non-SCM USB-SCSI converters which support multiple targets include:
- Adaptec USBXchange and USB2Xchange. Not supported in mainline kernel,
though someone posted a patch a few years ago.
- Second Wave SCUSBee. Also unsupported, and figuring out how it works
might be tricky (wading through lots of PowerPC Mac OS driver code).
- Ratoc U2SCX and U2SCX-LVD. Not supported in Linux either as far as I
know. (I don't have one.)

Any of those would need specific support in the kernel anyway I think,
since (as far as I know) there isn't a standard way to access multiple
targets.


Mark
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Alan Stern
2014-10-09 21:05:10 UTC
Permalink
Post by Mark Knibbs
Since setting max_lun to 0 in the US_FL_SINGLE_LUN case is done elsewhere,
how about setting max_lun to 7 for US_FL_SCM_MULT_TARG next to that? So the
/*
* Determine the max LUN value for bulk-only devices, except in
* the US_FL_SINGLE_LUN and US_FL_SCM_MULT_TARG cases where max_lun
* is set by usb_stor_probe2().
*/
if (us->protocol == USB_PR_BULK &&
!(us->fflags & (US_FL_SINGLE_LUN | US_FL_SCM_MULT_TARG))) {
mutex_lock(&us->dev_mutex);
us->max_lun = usb_stor_Bulk_max_lun(us);
mutex_unlock(&us->dev_mutex);
}
/* fix for single-lun devices */
if (us->fflags & US_FL_SINGLE_LUN) {
us->max_lun = 0;
} else if (us->fflags & US_FL_SCM_MULT_TARG) {
/*
* Multiple-target devices can have different numbers of
* LUNs on different targets. Allow all to be probed.
*/
us->max_lun = 7;
}
That would also work if us->protocol != USB_PR_BULK.
Actually it wouldn't, because now that I think back, I remember that
other transports have no way to indicate the target number. (In fact,
the Bulk-only transport doesn't have a way to do this either -- the
mechanism used by these SCM_MULT_TARG devices is an extension to the
protocol.) So it doesn't make much sense to allow SCM_MULT_TARG unless
USB_PR_BULK is used.
Post by Mark Knibbs
Post by Alan Stern
Do you know that all SCM_MULT_TARG devices use the Bulk-only transport?
Good question. It seems SCM converters support bulk-only and "CBC" (CBI
with no command completion interrupt?); there's a comment in the Windows
; DriverFlags field bitmap definition
; ...
; 0x00000010 => Force CBC Protocol
; 0x00000020 => Force BONLY Protocol
I don't know what CBC is. In any case, the CB code in usb-storage
doesn't support multiple targets.
Post by Mark Knibbs
bInterfaceClass 8 Mass Storage
bInterfaceSubClass 6 SCSI
bInterfaceProtocol 80 Bulk (Zip)
iInterface 4 BONLY and CBC Interface
Three entries for SCM-based converters in unusual-devs.h have USB_SC_SCSI,
USB_PR_BULK though (as opposed to USB_SC_DEVICE, USB_PR_DEVICE): 04E6:000B,
04E6:000C, and 050D:0115. I don't have any of those so can't say whether
USB_SC_SCSI/USB_PR_BULK is necessary for those quirk entries.
So the answer to your question is probably yes. But it might be better to
not rely on that.
Actually we can rely on it. The other transports don't use multiple
targets.
Post by Mark Knibbs
switch (us->protocol) {
us->transport_name = "Control/Bulk";
us->transport = usb_stor_CB_transport;
us->transport_reset = usb_stor_CB_reset;
us->max_lun = 7;
break;
Could a hacky way to get an SCM converter to work with multiple LUNs be to
just change its useProtocol UNUSUAL_DEV entry to USB_PR_CB? That should
force the kernel to use control/bulk protocol, and thus set max_lun to 7
with no other code change.
It will not work with targets beyond 0. It may not work at all.
Post by Mark Knibbs
By the way: is there any technical advantage to bulk-only vs control/bulk
protocol?
Yes; it has less overhead. For one thing, control messages involve
more packets going back and forth than bulk messages do. For another,
CB does not convey status information, so the kernel has to
specifically ask for sense data after every non-data-in command.
Post by Mark Knibbs
To digress slightly, I just built a kernel with USB_PR_CB instead of
USB_PR_DEVICE for the SCM converter quirk. A couple of points on testing
- Throughput is faster with CB than bulk-only. Using sg_rbuf to issue
512KB READ BUFFER commands gives 865,160 bytes/sec with bulk-only but
917,865 with CB; about 6% faster. Smaller transfer sizes have a much
greater difference; CB was 100% faster for 1KB transfer size (BOT 128000,
CB 256000) and 33% faster for 8KB transfers (BOT 511996, CB 682667). Does
the CB protocol have less command overhead?
- I had one single-LUN drive connected, but 8 block devices were created
(one for each LUN). With the bulk-only protocol but max_lun set to 7,
there were no bogus/phantom drives. I wonder if the SCM converters, when
using Control/Bulk protocol, need target/LUN information in one of the
reserved bytes of the ADSC setup packet (bytes 2, 3 or 5)...
Don't know. You'll have to ask the manufacturer.
Post by Mark Knibbs
Post by Alan Stern
Post by Mark Knibbs
Could any other multiple-LUN-supporting devices be affected by this issue?
Every multiple-target USB device will be affected.
Right. Are there any others, other than USB-SCSI converters?
I don't know what you mean. "Target" and "LUN" are SCSI concepts; they
don't apply to anything else. Nor does the usb-storage driver.
Post by Mark Knibbs
- Adaptec USBXchange and USB2Xchange. Not supported in mainline kernel,
though someone posted a patch a few years ago.
- Second Wave SCUSBee. Also unsupported, and figuring out how it works
might be tricky (wading through lots of PowerPC Mac OS driver code).
- Ratoc U2SCX and U2SCX-LVD. Not supported in Linux either as far as I
know. (I don't have one.)
Any of those would need specific support in the kernel anyway I think,
since (as far as I know) there isn't a standard way to access multiple
targets.
No, there isn't.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Mark Knibbs
2014-10-16 21:16:43 UTC
Permalink
Hi,

This patch does two things for SCM eUSCSI USB-SCSI converters:

1. SCM eUSCSI bridge devices are hard-wired to use SCSI ID 7. On connecting
the converter, access to that ID is attempted during the bus scan. Asking
the converter to issue INQUIRY commands to itself isn't very polite and
wastes time. Set this_id to 7 so __scsi_scan_target() skips it in the scan.
(This replaces my previously-posted patch
"[PATCH v2] storage: Don't scan target 7 for SCM USB-SCSI converters".)


2. Enable multi-LUN support. eUSCSI devices don't support Get Max LUN
requests, returning an error (-32). [Different targets could have different
numbers of LUNs, so it wouldn't make sense to return a particular value in
response to Get Max LUN.]

usb_stor_scan_dwork() does this:
/* For bulk-only devices, determine the max LUN value */
if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
mutex_lock(&us->dev_mutex);
us->max_lun = usb_stor_Bulk_max_lun(us);
mutex_unlock(&us->dev_mutex);

It avoids calling usb_stor_Bulk_max_lun() if US_FL_SINGLE_LUN, but not for
US_FL_SCM_MULT_TARG. Since usb_stor_Bulk_max_lun() returns 0 in the error
case, us->max_lun was always set to 0.

[If the user doesn't want multi-LUN support (perhaps there are SCSI devices
which respond to commands on all LUNs?), the US_FL_SINGLE_LUN quirk can be
specified on the kernel command line.]


Signed-off-by: Mark Knibbs <markk-yYnZraf+/sb10XsdtD+***@public.gmane.org>

---
diff -up linux-3.17/drivers/usb/storage/usb.c.orig linux-3.17/drivers/usb/storage/usb.c
--- linux-3.17/drivers/usb/storage/usb.c.orig 2014-10-05 20:23:04.000000000 +0100
+++ linux-3.17/drivers/usb/storage/usb.c 2014-10-16 22:11:31.000000000 +0100
@@ -877,7 +877,9 @@ static void usb_stor_scan_dwork(struct w
dev_dbg(dev, "starting scan\n");

/* For bulk-only devices, determine the max LUN value */
- if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
+ if (us->protocol == USB_PR_BULK &&
+ !(us->fflags & US_FL_SINGLE_LUN) &&
+ !(us->fflags & US_FL_SCM_MULT_TARG)) {
mutex_lock(&us->dev_mutex);
us->max_lun = usb_stor_Bulk_max_lun(us);
mutex_unlock(&us->dev_mutex);
@@ -976,13 +978,24 @@ int usb_stor_probe2(struct us_data *us)
usb_stor_dbg(us, "Transport: %s\n", us->transport_name);
usb_stor_dbg(us, "Protocol: %s\n", us->protocol_name);

+ if (us->fflags & US_FL_SCM_MULT_TARG) {
+ /*
+ * SCM eUSCSI bridge devices can have different numbers
+ * of LUNs on different targets; allow all to be probed.
+ */
+ us->max_lun = 7;
+ /* The eUSCSI itself has ID 7, so avoid scanning that */
+ us_to_host(us)->this_id = 7;
+ /* max_id is 8 initially, so no need to set it here */
+ } else {
+ /* In the normal case there is only a single target */
+ us_to_host(us)->max_id = 1;
+ }
+
/* fix for single-lun devices */
if (us->fflags & US_FL_SINGLE_LUN)
us->max_lun = 0;

- if (!(us->fflags & US_FL_SCM_MULT_TARG))
- us_to_host(us)->max_id = 1;

Loading...