Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 289416
b: refs/heads/master
c: ceb3f91
h: refs/heads/master
v: v3
  • Loading branch information
Sebastian Andrzej Siewior committed Dec 22, 2011
1 parent 5bd18f1 commit e49cf0c
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 22188f4a933c6e86ac67f52028895c795896492e
refs/heads/master: ceb3f91fd53c9fbd7b292fc2754ba4efffeeeedb
70 changes: 60 additions & 10 deletions trunk/drivers/usb/storage/uas.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ struct uas_dev_info {
unsigned use_streams:1;
unsigned uas_sense_old:1;
struct scsi_cmnd *cmnd;
struct urb *status_urb; /* used only if stream support is available */
};

enum {
Expand All @@ -117,6 +118,7 @@ struct uas_cmd_info {
unsigned int state;
unsigned int stream;
struct urb *cmd_urb;
/* status_urb is used only if stream support isn't available */
struct urb *status_urb;
struct urb *data_in_urb;
struct urb *data_out_urb;
Expand Down Expand Up @@ -180,7 +182,6 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)

cmnd->result = sense_iu->status;
cmnd->scsi_done(cmnd);
usb_free_urb(urb);
}

static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
Expand All @@ -205,7 +206,6 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)

cmnd->result = sense_iu->status;
cmnd->scsi_done(cmnd);
usb_free_urb(urb);
}

static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
Expand All @@ -214,7 +214,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_STATUS_URB;
cmdinfo->state = direction;
err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
if (err) {
spin_lock(&uas_work_lock);
Expand All @@ -231,10 +231,12 @@ static void uas_stat_cmplt(struct urb *urb)
struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
struct scsi_cmnd *cmnd;
u16 tag;
int ret;

if (urb->status) {
dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
usb_free_urb(urb);
if (devinfo->use_streams)
usb_free_urb(urb);
return;
}

Expand All @@ -244,7 +246,13 @@ static void uas_stat_cmplt(struct urb *urb)
else
cmnd = scsi_host_find_tag(shost, tag - 1);
if (!cmnd) {
usb_free_urb(urb);
if (devinfo->use_streams) {
usb_free_urb(urb);
return;
}
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret)
dev_err(&urb->dev->dev, "failed submit status urb\n");
return;
}

Expand All @@ -270,6 +278,15 @@ static void uas_stat_cmplt(struct urb *urb)
scmd_printk(KERN_ERR, cmnd,
"Bogus IU (%d) received on status pipe\n", iu->iu_id);
}

if (devinfo->use_streams) {
usb_free_urb(urb);
return;
}

ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret)
dev_err(&urb->dev->dev, "failed submit status urb\n");
}

static void uas_data_cmplt(struct urb *urb)
Expand Down Expand Up @@ -300,7 +317,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
}

static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
struct scsi_cmnd *cmnd, u16 stream_id)
struct Scsi_Host *shost, u16 stream_id)
{
struct usb_device *udev = devinfo->udev;
struct urb *urb = usb_alloc_urb(0, gfp);
Expand All @@ -314,7 +331,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
goto free;

usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
uas_stat_cmplt, cmnd->device->host);
uas_stat_cmplt, shost);
urb->stream_id = stream_id;
urb->transfer_flags |= URB_FREE_BUFFER;
out:
Expand Down Expand Up @@ -376,8 +393,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;

if (cmdinfo->state & ALLOC_STATUS_URB) {
cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd,
cmdinfo->stream);
cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp,
cmnd->device->host, cmdinfo->stream);
if (!cmdinfo->status_urb)
return SCSI_MLQUEUE_DEVICE_BUSY;
cmdinfo->state &= ~ALLOC_STATUS_URB;
Expand Down Expand Up @@ -486,7 +503,8 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
}

if (!devinfo->use_streams) {
cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB |
ALLOC_STATUS_URB | SUBMIT_STATUS_URB);
cmdinfo->stream = 0;
}

Expand Down Expand Up @@ -685,6 +703,29 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo)
}
}

static int uas_alloc_status_urb(struct uas_dev_info *devinfo,
struct Scsi_Host *shost)
{
if (devinfo->use_streams) {
devinfo->status_urb = NULL;
return 0;
}

devinfo->status_urb = uas_alloc_sense_urb(devinfo, GFP_KERNEL,
shost, 0);
if (!devinfo->status_urb)
goto err_s_urb;

if (usb_submit_urb(devinfo->status_urb, GFP_KERNEL))
goto err_submit_urb;

return 0;
err_submit_urb:
usb_free_urb(devinfo->status_urb);
err_s_urb:
return -ENOMEM;
}

static void uas_free_streams(struct uas_dev_info *devinfo)
{
struct usb_device *udev = devinfo->udev;
Expand Down Expand Up @@ -739,10 +780,17 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)

shost->hostdata[0] = (unsigned long)devinfo;

result = uas_alloc_status_urb(devinfo, shost);
if (result)
goto err_alloc_status;

scsi_scan_host(shost);
usb_set_intfdata(intf, shost);
return result;

err_alloc_status:
scsi_remove_host(shost);
shost = NULL;
deconfig_eps:
uas_free_streams(devinfo);
free:
Expand Down Expand Up @@ -770,6 +818,8 @@ static void uas_disconnect(struct usb_interface *intf)
struct uas_dev_info *devinfo = (void *)shost->hostdata[0];

scsi_remove_host(shost);
usb_kill_urb(devinfo->status_urb);
usb_free_urb(devinfo->status_urb);
uas_free_streams(devinfo);
kfree(devinfo);
}
Expand Down

0 comments on commit e49cf0c

Please sign in to comment.