diff options
Diffstat (limited to 'drivers/usb/storage/uas.c')
-rw-r--r-- | drivers/usb/storage/uas.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 08f9296431e9..c8a577309e8f 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -279,17 +279,17 @@ static bool uas_evaluate_response_iu(struct response_iu *riu, struct scsi_cmnd * switch (response_code) { case RC_INCORRECT_LUN: - cmnd->result = DID_BAD_TARGET << 16; + set_host_byte(cmnd, DID_BAD_TARGET); break; case RC_TMF_SUCCEEDED: - cmnd->result = DID_OK << 16; + set_host_byte(cmnd, DID_OK); break; case RC_TMF_NOT_SUPPORTED: - cmnd->result = DID_TARGET_FAILURE << 16; + set_host_byte(cmnd, DID_TARGET_FAILURE); break; default: uas_log_cmd_state(cmnd, "response iu", response_code); - cmnd->result = DID_ERROR << 16; + set_host_byte(cmnd, DID_ERROR); break; } @@ -660,10 +660,9 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, spin_lock_irqsave(&devinfo->lock, flags); if (devinfo->resetting) { - cmnd->result = DID_ERROR << 16; + set_host_byte(cmnd, DID_ERROR); cmnd->scsi_done(cmnd); - spin_unlock_irqrestore(&devinfo->lock, flags); - return 0; + goto zombie; } /* Find a free uas-tag */ @@ -699,6 +698,16 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB); err = uas_submit_urbs(cmnd, devinfo); + /* + * in case of fatal errors the SCSI layer is peculiar + * a command that has finished is a success for the purpose + * of queueing, no matter how fatal the error + */ + if (err == -ENODEV) { + set_host_byte(cmnd, DID_ERROR); + cmnd->scsi_done(cmnd); + goto zombie; + } if (err) { /* If we did nothing, give up now */ if (cmdinfo->state & SUBMIT_STATUS_URB) { @@ -709,6 +718,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, } devinfo->cmnd[idx] = cmnd; +zombie: spin_unlock_irqrestore(&devinfo->lock, flags); return 0; } @@ -827,17 +837,24 @@ static int uas_slave_alloc(struct scsi_device *sdev) */ blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); - if (devinfo->flags & US_FL_MAX_SECTORS_64) - blk_queue_max_hw_sectors(sdev->request_queue, 64); - else if (devinfo->flags & US_FL_MAX_SECTORS_240) - blk_queue_max_hw_sectors(sdev->request_queue, 240); - return 0; } static int uas_slave_configure(struct scsi_device *sdev) { struct uas_dev_info *devinfo = sdev->hostdata; + struct device *dev = sdev->host->dma_dev; + + if (devinfo->flags & US_FL_MAX_SECTORS_64) + blk_queue_max_hw_sectors(sdev->request_queue, 64); + else if (devinfo->flags & US_FL_MAX_SECTORS_240) + blk_queue_max_hw_sectors(sdev->request_queue, 240); + else if (devinfo->udev->speed >= USB_SPEED_SUPER) + blk_queue_max_hw_sectors(sdev->request_queue, 2048); + + blk_queue_max_hw_sectors(sdev->request_queue, + min_t(size_t, queue_max_hw_sectors(sdev->request_queue), + dma_max_mapping_size(dev) >> SECTOR_SHIFT)); if (devinfo->flags & US_FL_NO_REPORT_OPCODES) sdev->no_report_opcodes = 1; @@ -1023,7 +1040,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) shost->can_queue = devinfo->qdepth - 2; usb_set_intfdata(intf, shost); - result = scsi_add_host(shost, &intf->dev); + result = scsi_add_host_with_dma(shost, &intf->dev, udev->bus->sysdev); if (result) goto free_streams; |