diff options
Diffstat (limited to 'drivers/usb/storage')
| -rw-r--r-- | drivers/usb/storage/scsiglue.c | 4 | ||||
| -rw-r--r-- | drivers/usb/storage/sierra_ms.c | 2 | ||||
| -rw-r--r-- | drivers/usb/storage/uas.c | 91 | ||||
| -rw-r--r-- | drivers/usb/storage/unusual_devs.h | 7 | 
4 files changed, 69 insertions, 35 deletions
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index a688b1e686e..689ee1fb702 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -285,7 +285,7 @@ static int slave_configure(struct scsi_device *sdev)  /* queue a command */  /* This is always called with scsi_lock(host) held */ -static int queuecommand(struct scsi_cmnd *srb, +static int queuecommand_lck(struct scsi_cmnd *srb,  			void (*done)(struct scsi_cmnd *))  {  	struct us_data *us = host_to_us(srb->device->host); @@ -315,6 +315,8 @@ static int queuecommand(struct scsi_cmnd *srb,  	return 0;  } +static DEF_SCSI_QCMD(queuecommand) +  /***********************************************************************   * Error handling functions   ***********************************************************************/ diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c index 57fc2f532ca..ceba512f84d 100644 --- a/drivers/usb/storage/sierra_ms.c +++ b/drivers/usb/storage/sierra_ms.c @@ -121,7 +121,7 @@ static ssize_t show_truinst(struct device *dev, struct device_attribute *attr,  	}  	return result;  } -static DEVICE_ATTR(truinst, S_IWUGO | S_IRUGO, show_truinst, NULL); +static DEVICE_ATTR(truinst, S_IRUGO, show_truinst, NULL);  int sierra_ms_init(struct us_data *us)  { diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 2054b1e25a6..23f0dd9c36d 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -49,14 +49,17 @@ struct command_iu {  	__u8 cdb[16];	/* XXX: Overflow-checking tools may misunderstand */  }; +/* + * Also used for the Read Ready and Write Ready IUs since they have the + * same first four bytes + */  struct sense_iu {  	__u8 iu_id;  	__u8 rsvd1;  	__be16 tag;  	__be16 status_qual;  	__u8 status; -	__u8 service_response; -	__u8 rsvd8[6]; +	__u8 rsvd7[7];  	__be16 len;  	__u8 sense[SCSI_SENSE_BUFFERSIZE];  }; @@ -97,8 +100,8 @@ struct uas_dev_info {  };  enum { -	ALLOC_SENSE_URB		= (1 << 0), -	SUBMIT_SENSE_URB	= (1 << 1), +	ALLOC_STATUS_URB	= (1 << 0), +	SUBMIT_STATUS_URB	= (1 << 1),  	ALLOC_DATA_IN_URB	= (1 << 2),  	SUBMIT_DATA_IN_URB	= (1 << 3),  	ALLOC_DATA_OUT_URB	= (1 << 4), @@ -112,7 +115,7 @@ struct uas_cmd_info {  	unsigned int state;  	unsigned int stream;  	struct urb *cmd_urb; -	struct urb *sense_urb; +	struct urb *status_urb;  	struct urb *data_in_urb;  	struct urb *data_out_urb;  	struct list_head list; @@ -138,7 +141,7 @@ static void uas_do_work(struct work_struct *work)  		struct scsi_pointer *scp = (void *)cmdinfo;  		struct scsi_cmnd *cmnd = container_of(scp,  							struct scsi_cmnd, SCp); -		uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_KERNEL); +		uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);  	}  } @@ -204,7 +207,7 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,  	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;  	int err; -	cmdinfo->state = direction | SUBMIT_SENSE_URB; +	cmdinfo->state = direction | SUBMIT_STATUS_URB;  	err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);  	if (err) {  		spin_lock(&uas_work_lock); @@ -294,7 +297,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,  	if (!urb)  		goto out; -	iu = kmalloc(sizeof(*iu), gfp); +	iu = kzalloc(sizeof(*iu), gfp);  	if (!iu)  		goto free; @@ -325,16 +328,13 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,  	if (len < 0)  		len = 0;  	len = ALIGN(len, 4); -	iu = kmalloc(sizeof(*iu) + len, gfp); +	iu = kzalloc(sizeof(*iu) + len, gfp);  	if (!iu)  		goto free;  	iu->iu_id = IU_ID_COMMAND;  	iu->tag = cpu_to_be16(stream_id); -	if (sdev->ordered_tags && (cmnd->request->cmd_flags & REQ_HARDBARRIER)) -		iu->prio_attr = UAS_ORDERED_TAG; -	else -		iu->prio_attr = UAS_SIMPLE_TAG; +	iu->prio_attr = UAS_SIMPLE_TAG;  	iu->len = len;  	int_to_scsilun(sdev->lun, &iu->lun);  	memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len); @@ -360,21 +360,21 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,  {  	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; -	if (cmdinfo->state & ALLOC_SENSE_URB) { -		cmdinfo->sense_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd, -							cmdinfo->stream); -		if (!cmdinfo->sense_urb) +	if (cmdinfo->state & ALLOC_STATUS_URB) { +		cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd, +							  cmdinfo->stream); +		if (!cmdinfo->status_urb)  			return SCSI_MLQUEUE_DEVICE_BUSY; -		cmdinfo->state &= ~ALLOC_SENSE_URB; +		cmdinfo->state &= ~ALLOC_STATUS_URB;  	} -	if (cmdinfo->state & SUBMIT_SENSE_URB) { -		if (usb_submit_urb(cmdinfo->sense_urb, gfp)) { +	if (cmdinfo->state & SUBMIT_STATUS_URB) { +		if (usb_submit_urb(cmdinfo->status_urb, gfp)) {  			scmd_printk(KERN_INFO, cmnd,  					"sense urb submission failure\n");  			return SCSI_MLQUEUE_DEVICE_BUSY;  		} -		cmdinfo->state &= ~SUBMIT_SENSE_URB; +		cmdinfo->state &= ~SUBMIT_STATUS_URB;  	}  	if (cmdinfo->state & ALLOC_DATA_IN_URB) { @@ -433,7 +433,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,  	return 0;  } -static int uas_queuecommand(struct scsi_cmnd *cmnd, +static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,  					void (*done)(struct scsi_cmnd *))  {  	struct scsi_device *sdev = cmnd->device; @@ -443,7 +443,7 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,  	BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); -	if (!cmdinfo->sense_urb && sdev->current_cmnd) +	if (!cmdinfo->status_urb && sdev->current_cmnd)  		return SCSI_MLQUEUE_DEVICE_BUSY;  	if (blk_rq_tagged(cmnd->request)) { @@ -455,7 +455,7 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,  	cmnd->scsi_done = done; -	cmdinfo->state = ALLOC_SENSE_URB | SUBMIT_SENSE_URB | +	cmdinfo->state = ALLOC_STATUS_URB | SUBMIT_STATUS_URB |  			ALLOC_CMD_URB | SUBMIT_CMD_URB;  	switch (cmnd->sc_data_direction) { @@ -478,8 +478,8 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,  	err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC);  	if (err) {  		/* If we did nothing, give up now */ -		if (cmdinfo->state & SUBMIT_SENSE_URB) { -			usb_free_urb(cmdinfo->sense_urb); +		if (cmdinfo->state & SUBMIT_STATUS_URB) { +			usb_free_urb(cmdinfo->status_urb);  			return SCSI_MLQUEUE_DEVICE_BUSY;  		}  		spin_lock(&uas_work_lock); @@ -491,6 +491,8 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,  	return 0;  } +static DEF_SCSI_QCMD(uas_queuecommand) +  static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)  {  	struct scsi_device *sdev = cmnd->device; @@ -579,6 +581,34 @@ static struct usb_device_id uas_usb_ids[] = {  };  MODULE_DEVICE_TABLE(usb, uas_usb_ids); +static int uas_is_interface(struct usb_host_interface *intf) +{ +	return (intf->desc.bInterfaceClass == USB_CLASS_MASS_STORAGE && +		intf->desc.bInterfaceSubClass == USB_SC_SCSI && +		intf->desc.bInterfaceProtocol == USB_PR_UAS); +} + +static int uas_switch_interface(struct usb_device *udev, +						struct usb_interface *intf) +{ +	int i; + +	if (uas_is_interface(intf->cur_altsetting)) +		return 0; + +	for (i = 0; i < intf->num_altsetting; i++) { +		struct usb_host_interface *alt = &intf->altsetting[i]; +		if (alt == intf->cur_altsetting) +			continue; +		if (uas_is_interface(alt)) +			return usb_set_interface(udev, +						alt->desc.bInterfaceNumber, +						alt->desc.bAlternateSetting); +	} + +	return -ENODEV; +} +  static void uas_configure_endpoints(struct uas_dev_info *devinfo)  {  	struct usb_host_endpoint *eps[4] = { }; @@ -652,13 +682,8 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)  	struct uas_dev_info *devinfo;  	struct usb_device *udev = interface_to_usbdev(intf); -	if (id->bInterfaceProtocol == 0x50) { -		int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; -/* XXX: Shouldn't assume that 1 is the alternative we want */ -		int ret = usb_set_interface(udev, ifnum, 1); -		if (ret) -			return -ENODEV; -	} +	if (uas_switch_interface(udev, intf)) +		return -ENODEV;  	devinfo = kmalloc(sizeof(struct uas_dev_info), GFP_KERNEL);  	if (!devinfo) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6ccdd3dd525..fcc1e32ce25 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -481,6 +481,13 @@ UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,  		USB_SC_DEVICE, USB_PR_DEVICE, NULL,  		US_FL_MAX_SECTORS_64), +/* Reported by Vitaly Kuznetsov <vitty@altlinux.ru> */ +UNUSUAL_DEV(  0x04e8, 0x5122, 0x0000, 0x9999, +		"Samsung", +		"YP-CP3", +		USB_SC_DEVICE, USB_PR_DEVICE, NULL, +		US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG), +  /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.   * Device uses standards-violating 32-byte Bulk Command Block Wrappers and   * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.  | 
