// SPDX-License-Identifier: GPL-2.0 /* * USB Attached SCSI * Note that this is not the same as the USB Mass Storage driver * * Copyright Hans de Goede <hdegoede@redhat.com> for Red Hat, Inc. 2013 - 2016 * Copyright Matthew Wilcox for Intel Corp, 2010 * Copyright Sarah Sharp for Intel Corp, 2010
*/
/* I hate forward declarations, but I actually have a loop */ staticint uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_dev_info *devinfo); staticvoid uas_do_work(struct work_struct *work); staticint uas_try_complete(struct scsi_cmnd *cmnd, constchar *caller); staticvoid uas_free_streams(struct uas_dev_info *devinfo); staticvoid uas_log_cmd_state(struct scsi_cmnd *cmnd, constchar *prefix, int status);
/* * This driver needs its own workqueue, as we need to control memory allocation. * * In the course of error handling and power management uas_wait_for_pending_cmnds() * needs to flush pending work items. In these contexts we cannot allocate memory * by doing block IO as we would deadlock. For the same reason we cannot wait * for anything allocating memory not heeding these constraints. * * So we have to control all work items that can be on the workqueue we flush. * Hence we cannot share a queue and need our own.
*/ staticstruct workqueue_struct *workqueue;
if (cmdinfo->state & SUBMIT_CMD_URB)
usb_free_urb(cmdinfo->cmd_urb);
/* data urbs may have never gotten their submit flag set */ if (!(cmdinfo->state & DATA_IN_URB_INFLIGHT))
usb_free_urb(cmdinfo->data_in_urb); if (!(cmdinfo->state & DATA_OUT_URB_INFLIGHT))
usb_free_urb(cmdinfo->data_out_urb);
}
if (status) { if (status != -ENOENT && status != -ECONNRESET && status != -ESHUTDOWN)
dev_err(&urb->dev->dev, "stat urb: status %d\n", status); goto out;
}
idx = be16_to_cpup(&iu->tag) - 1; if (idx >= MAX_CMNDS || !devinfo->cmnd[idx]) {
dev_err(&urb->dev->dev, "stat urb: no pending cmd for uas-tag %d\n", idx + 1); goto out;
}
/* Unlinking of data urbs must be done without holding the lock */ if (data_in_urb) {
usb_unlink_urb(data_in_urb);
usb_put_urb(data_in_urb);
} if (data_out_urb) {
usb_unlink_urb(data_out_urb);
usb_put_urb(data_out_urb);
}
}
/* Data urbs should not complete before the cmd urb is submitted */ if (cmdinfo->state & SUBMIT_CMD_URB) {
uas_log_cmd_state(cmnd, "unexpected data cmplt", 0); goto out;
}
if (status) { if (status != -ENOENT && status != -ECONNRESET && status != -ESHUTDOWN)
uas_log_cmd_state(cmnd, "data cmplt err", status); /* error: no data transfered */
scsi_set_resid(cmnd, sdb->length);
set_host_byte(cmnd, DID_ERROR);
} else {
scsi_set_resid(cmnd, sdb->length - urb->actual_length);
}
uas_try_complete(cmnd, __func__);
out:
usb_free_urb(urb);
spin_unlock_irqrestore(&devinfo->lock, flags);
}
/* * Why should I request the Status IU before sending the Command IU? Spec * says to, but also says the device may receive them in any order. Seems * daft to me.
*/
switch (cmnd->sc_data_direction) { case DMA_FROM_DEVICE:
cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB; break; case DMA_BIDIRECTIONAL:
cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB;
fallthrough; case DMA_TO_DEVICE:
cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB; break; case DMA_NONE: break;
}
if (!devinfo->use_streams)
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_NO_CONNECT);
scsi_done(cmnd); goto zombie;
} if (err) { /* If we did nothing, give up now */ if (cmdinfo->state & SUBMIT_STATUS_URB) {
spin_unlock_irqrestore(&devinfo->lock, flags); return SCSI_MLQUEUE_DEVICE_BUSY;
}
uas_add_work(cmnd);
}
/* * For now we do not support actually sending an abort to the device, so * this eh always fails. Still we must define it to make sure that we've * dropped all references to the cmnd in question once this function exits.
*/ staticint uas_eh_abort_handler(struct scsi_cmnd *cmnd)
{ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd); struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; struct urb *data_in_urb = NULL; struct urb *data_out_urb = NULL; unsignedlong flags;
spin_lock_irqsave(&devinfo->lock, flags);
uas_log_cmd_state(cmnd, __func__, 0);
/* Ensure that try_complete does not call scsi_done */
cmdinfo->state |= COMMAND_ABORTED;
/* Drop all refs to this cmnd, kill data urbs to break their ref */
devinfo->cmnd[cmdinfo->uas_tag - 1] = NULL; if (cmdinfo->state & DATA_IN_URB_INFLIGHT)
data_in_urb = usb_get_urb(cmdinfo->data_in_urb); if (cmdinfo->state & DATA_OUT_URB_INFLIGHT)
data_out_urb = usb_get_urb(cmdinfo->data_out_urb);
uas_free_unsubmitted_urbs(cmnd);
spin_unlock_irqrestore(&devinfo->lock, flags);
if (data_in_urb) {
usb_kill_urb(data_in_urb);
usb_put_urb(data_in_urb);
} if (data_out_urb) {
usb_kill_urb(data_out_urb);
usb_put_urb(data_out_urb);
}
/* * Some USB storage devices reset if the IO advice hints grouping mode * page is queried. Hence skip that mode page.
*/
sdev->sdev_bflags |= BLIST_SKIP_IO_HINTS;
if (devinfo->flags & US_FL_NO_REPORT_OPCODES)
sdev->no_report_opcodes = 1;
/* A few buggy USB-ATA bridges don't understand FUA */ if (devinfo->flags & US_FL_BROKEN_FUA)
sdev->broken_fua = 1;
/* UAS also needs to support FL_ALWAYS_SYNC */ if (devinfo->flags & US_FL_ALWAYS_SYNC) {
sdev->skip_ms_page_3f = 1;
sdev->skip_ms_page_8 = 1;
sdev->wce_default_on = 1;
}
/* Some disks cannot handle READ_CAPACITY_16 */ if (devinfo->flags & US_FL_NO_READ_CAPACITY_16)
sdev->no_read_capacity_16 = 1;
/* Some disks cannot handle WRITE_SAME */ if (devinfo->flags & US_FL_NO_SAME)
sdev->no_write_same = 1; /* * Some disks return the total number of blocks in response * to READ CAPACITY rather than the highest block number. * If this device makes that mistake, tell the sd driver.
*/ if (devinfo->flags & US_FL_FIX_CAPACITY)
sdev->fix_capacity = 1;
/* * in some cases we have to guess
*/ if (devinfo->flags & US_FL_CAPACITY_HEURISTICS)
sdev->guess_capacity = 1;
/* * Some devices report generic values until the media has been * accessed. Force a READ(10) prior to querying device * characteristics.
*/
sdev->read_before_ms = 1;
/* * Some devices don't like MODE SENSE with page=0x3f, * which is the command used for checking if a device * is write-protected. Now that we tell the sd driver * to do a 192-byte transfer with this command the * majority of devices work fine, but a few still can't * handle it. The sd driver will simply assume those * devices are write-enabled.
*/ if (devinfo->flags & US_FL_NO_WP_DETECT)
sdev->skip_ms_page_3f = 1;
staticconststruct scsi_host_template uas_host_template = {
.module = THIS_MODULE,
.name = "uas",
.queuecommand = uas_queuecommand,
.target_alloc = uas_target_alloc,
.sdev_init = uas_sdev_init,
.sdev_configure = uas_sdev_configure,
.eh_abort_handler = uas_eh_abort_handler,
.eh_device_reset_handler = uas_eh_device_reset_handler,
.this_id = -1,
.skip_settle_delay = 1, /* * The protocol has no requirements on alignment in the strict sense. * Controllers may or may not have alignment restrictions. * As this is not exported, we use an extremely conservative guess.
*/
.dma_alignment = 511,
.dma_boundary = PAGE_SIZE - 1,
.cmd_size = sizeof(struct uas_cmd_info),
};
staticint uas_cmnd_list_empty(struct uas_dev_info *devinfo)
{ unsignedlong flags; int i, r = 1;
spin_lock_irqsave(&devinfo->lock, flags);
for (i = 0; i < devinfo->qdepth; i++) { if (devinfo->cmnd[i]) {
r = 0; /* Not empty */ break;
}
}
spin_unlock_irqrestore(&devinfo->lock, flags);
return r;
}
/* * Wait for any pending cmnds to complete, on usb-2 sense_urbs may temporarily * get empty while there still is more work to do due to sense-urbs completing * with a READ/WRITE_READY iu code, so keep waiting until the list gets empty.
*/ staticint uas_wait_for_pending_cmnds(struct uas_dev_info *devinfo)
{ unsignedlong start_time; int r;
start_time = jiffies; do {
flush_work(&devinfo->work);
r = usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 5000); if (r == 0) return -ETIME;
r = usb_wait_anchor_empty_timeout(&devinfo->data_urbs, 500); if (r == 0) return -ETIME;
if (time_after(jiffies, start_time + 5 * HZ)) return -ETIME;
} while (!uas_cmnd_list_empty(devinfo));
err = uas_configure_endpoints(devinfo); if (err && err != -ENODEV)
shost_printk(KERN_ERR, shost, "%s: alloc streams error %d after reset",
__func__, err);
/* we must unblock the host in every case lest we deadlock */
spin_lock_irqsave(shost->host_lock, flags);
scsi_report_bus_reset(shost, 0);
spin_unlock_irqrestore(shost->host_lock, flags);
/* * Put the device back in usb-storage mode on shutdown, as some BIOS-es * hang on reboot when the device is still in uas mode. Note the reset is * necessary as some devices won't revert to usb-storage mode without it.
*/ staticvoid uas_shutdown(struct usb_interface *intf)
{ struct usb_device *udev = interface_to_usbdev(intf); struct Scsi_Host *shost = usb_get_intfdata(intf); struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
MODULE_DESCRIPTION("USB Attached SCSI driver");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("USB_STORAGE");
MODULE_AUTHOR( "Hans de Goede , Matthew Wilcox and Sarah Sharp");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.