diff options
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r-- | drivers/usb/storage/scsiglue.c | 57 | ||||
-rw-r--r-- | drivers/usb/storage/uas.c | 57 | ||||
-rw-r--r-- | drivers/usb/storage/usb.c | 10 |
3 files changed, 63 insertions, 61 deletions
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 12cf9940e5b6..b31464740f6c 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -40,7 +40,6 @@ #include <scsi/scsi_eh.h> #include "usb.h" -#include <linux/usb/hcd.h> #include "scsiglue.h" #include "debug.h" #include "transport.h" @@ -76,12 +75,6 @@ static int slave_alloc (struct scsi_device *sdev) */ sdev->inquiry_len = 36; - /* - * Some host controllers may have alignment requirements. - * We'll play it safe by requiring 512-byte alignment always. - */ - blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); - /* Tell the SCSI layer if we know there is more than one LUN */ if (us->protocol == USB_PR_BULK && us->max_lun > 0) sdev->sdev_bflags |= BLIST_FORCELUN; @@ -89,7 +82,7 @@ static int slave_alloc (struct scsi_device *sdev) return 0; } -static int slave_configure(struct scsi_device *sdev) +static int device_configure(struct scsi_device *sdev, struct queue_limits *lim) { struct us_data *us = host_to_us(sdev->host); struct device *dev = us->pusb_dev->bus->sysdev; @@ -104,40 +97,28 @@ static int slave_configure(struct scsi_device *sdev) if (us->fflags & US_FL_MAX_SECTORS_MIN) max_sectors = PAGE_SIZE >> 9; - if (queue_max_hw_sectors(sdev->request_queue) > max_sectors) - blk_queue_max_hw_sectors(sdev->request_queue, - max_sectors); + lim->max_hw_sectors = min(lim->max_hw_sectors, max_sectors); } else if (sdev->type == TYPE_TAPE) { /* * Tapes need much higher max_sector limits, so just * raise it to the maximum possible (4 GB / 512) and * let the queue segment size sort out the real limit. */ - blk_queue_max_hw_sectors(sdev->request_queue, 0x7FFFFF); + lim->max_hw_sectors = 0x7FFFFF; } else if (us->pusb_dev->speed >= USB_SPEED_SUPER) { /* * USB3 devices will be limited to 2048 sectors. This gives us * better throughput on most devices. */ - blk_queue_max_hw_sectors(sdev->request_queue, 2048); + lim->max_hw_sectors = 2048; } /* * The max_hw_sectors should be up to maximum size of a mapping for * the device. Otherwise, a DMA API might fail on swiotlb environment. */ - 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)); - - /* - * Some USB host controllers can't do DMA; they have to use PIO. - * For such controllers we need to make sure the block layer sets - * up bounce buffers in addressable memory. - */ - if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus)) || - (bus_to_hcd(us->pusb_dev->bus)->localmem_pool != NULL)) - blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH); + lim->max_hw_sectors = min_t(size_t, + lim->max_hw_sectors, dma_max_mapping_size(dev) >> SECTOR_SHIFT); /* * We can't put these settings in slave_alloc() because that gets @@ -598,13 +579,22 @@ static ssize_t max_sectors_store(struct device *dev, struct device_attribute *at size_t count) { struct scsi_device *sdev = to_scsi_device(dev); + struct queue_limits lim; unsigned short ms; + int ret; - if (sscanf(buf, "%hu", &ms) > 0) { - blk_queue_max_hw_sectors(sdev->request_queue, ms); - return count; - } - return -EINVAL; + if (sscanf(buf, "%hu", &ms) <= 0) + return -EINVAL; + + blk_mq_freeze_queue(sdev->request_queue); + lim = queue_limits_start_update(sdev->request_queue); + lim.max_hw_sectors = ms; + ret = queue_limits_commit_update(sdev->request_queue, &lim); + blk_mq_unfreeze_queue(sdev->request_queue); + + if (ret) + return ret; + return count; } static DEVICE_ATTR_RW(max_sectors); @@ -642,12 +632,17 @@ static const struct scsi_host_template usb_stor_host_template = { .this_id = -1, .slave_alloc = slave_alloc, - .slave_configure = slave_configure, + .device_configure = device_configure, .target_alloc = target_alloc, /* lots of sg segments can be handled */ .sg_tablesize = SG_MAX_SEGMENTS, + /* + * Some host controllers may have alignment requirements. + * We'll play it safe by requiring 512-byte alignment always. + */ + .dma_alignment = 511, /* * Limit the total size of a transfer to 120 KB. diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 71ace274761f..a48870a87a29 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -533,7 +533,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp, * daft to me. */ -static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp) +static int uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp) { struct uas_dev_info *devinfo = cmnd->device->hostdata; struct urb *urb; @@ -541,30 +541,28 @@ static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp) urb = uas_alloc_sense_urb(devinfo, gfp, cmnd); if (!urb) - return NULL; + return -ENOMEM; usb_anchor_urb(urb, &devinfo->sense_urbs); err = usb_submit_urb(urb, gfp); if (err) { usb_unanchor_urb(urb); uas_log_cmd_state(cmnd, "sense submit err", err); usb_free_urb(urb); - return NULL; } - return urb; + return err; } static int uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_dev_info *devinfo) { struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd); - struct urb *urb; int err; lockdep_assert_held(&devinfo->lock); if (cmdinfo->state & SUBMIT_STATUS_URB) { - urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC); - if (!urb) - return SCSI_MLQUEUE_DEVICE_BUSY; + err = uas_submit_sense_urb(cmnd, GFP_ATOMIC); + if (err) + return err; cmdinfo->state &= ~SUBMIT_STATUS_URB; } @@ -572,7 +570,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC, cmnd, DMA_FROM_DEVICE); if (!cmdinfo->data_in_urb) - return SCSI_MLQUEUE_DEVICE_BUSY; + return -ENOMEM; cmdinfo->state &= ~ALLOC_DATA_IN_URB; } @@ -582,7 +580,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (err) { usb_unanchor_urb(cmdinfo->data_in_urb); uas_log_cmd_state(cmnd, "data in submit err", err); - return SCSI_MLQUEUE_DEVICE_BUSY; + return err; } cmdinfo->state &= ~SUBMIT_DATA_IN_URB; cmdinfo->state |= DATA_IN_URB_INFLIGHT; @@ -592,7 +590,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC, cmnd, DMA_TO_DEVICE); if (!cmdinfo->data_out_urb) - return SCSI_MLQUEUE_DEVICE_BUSY; + return -ENOMEM; cmdinfo->state &= ~ALLOC_DATA_OUT_URB; } @@ -602,7 +600,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (err) { usb_unanchor_urb(cmdinfo->data_out_urb); uas_log_cmd_state(cmnd, "data out submit err", err); - return SCSI_MLQUEUE_DEVICE_BUSY; + return err; } cmdinfo->state &= ~SUBMIT_DATA_OUT_URB; cmdinfo->state |= DATA_OUT_URB_INFLIGHT; @@ -611,7 +609,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (cmdinfo->state & ALLOC_CMD_URB) { cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, GFP_ATOMIC, cmnd); if (!cmdinfo->cmd_urb) - return SCSI_MLQUEUE_DEVICE_BUSY; + return -ENOMEM; cmdinfo->state &= ~ALLOC_CMD_URB; } @@ -621,7 +619,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (err) { usb_unanchor_urb(cmdinfo->cmd_urb); uas_log_cmd_state(cmnd, "cmd submit err", err); - return SCSI_MLQUEUE_DEVICE_BUSY; + return err; } cmdinfo->cmd_urb = NULL; cmdinfo->state &= ~SUBMIT_CMD_URB; @@ -698,7 +696,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd) * of queueing, no matter how fatal the error */ if (err == -ENODEV) { - set_host_byte(cmnd, DID_ERROR); + set_host_byte(cmnd, DID_NO_CONNECT); scsi_done(cmnd); goto zombie; } @@ -823,26 +821,19 @@ static int uas_slave_alloc(struct scsi_device *sdev) (struct uas_dev_info *)sdev->host->hostdata; sdev->hostdata = devinfo; - - /* - * 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. - */ - 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) +static int uas_device_configure(struct scsi_device *sdev, + struct queue_limits *lim) { struct uas_dev_info *devinfo = sdev->hostdata; + if (devinfo->flags & US_FL_MAX_SECTORS_64) + lim->max_hw_sectors = 64; + else if (devinfo->flags & US_FL_MAX_SECTORS_240) + lim->max_hw_sectors = 240; + if (devinfo->flags & US_FL_NO_REPORT_OPCODES) sdev->no_report_opcodes = 1; @@ -907,11 +898,17 @@ static const struct scsi_host_template uas_host_template = { .queuecommand = uas_queuecommand, .target_alloc = uas_target_alloc, .slave_alloc = uas_slave_alloc, - .slave_configure = uas_slave_configure, + .device_configure = uas_device_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), }; diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index d1ad6a2509ab..a49a31639f6f 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -47,6 +47,7 @@ #include <scsi/scsi_device.h> #include "usb.h" +#include <linux/usb/hcd.h> #include "scsiglue.h" #include "transport.h" #include "protocol.h" @@ -961,6 +962,15 @@ int usb_stor_probe1(struct us_data **pus, if (result) goto BadDevice; + /* + * Some USB host controllers can't do DMA; they have to use PIO. + * For such controllers we need to make sure the block layer sets + * up bounce buffers in addressable memory. + */ + if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus)) || + bus_to_hcd(us->pusb_dev->bus)->localmem_pool) + host->no_highmem = true; + /* Get the unusual_devs entries and the descriptors */ result = get_device_info(us, id, unusual_dev); if (result) |