Multiple LUNs not detected with SCM USB-SCSI converter

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux