summaryrefslogtreecommitdiff
path: root/drivers/scsi/scsi_scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
-rw-r--r--drivers/scsi/scsi_scan.c255
1 files changed, 169 insertions, 86 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 44680f65ea14..96d7e1a9a7c7 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -35,7 +35,7 @@
#include <linux/spinlock.h>
#include <linux/async.h>
#include <linux/slab.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -220,6 +220,7 @@ static int scsi_realloc_sdev_budget_map(struct scsi_device *sdev,
int new_shift = sbitmap_calculate_shift(depth);
bool need_alloc = !sdev->budget_map.map;
bool need_free = false;
+ unsigned int memflags;
int ret;
struct sbitmap sb_backup;
@@ -227,7 +228,7 @@ static int scsi_realloc_sdev_budget_map(struct scsi_device *sdev,
/*
* realloc if new shift is calculated, which is caused by setting
- * up one new default queue depth after calling ->slave_configure
+ * up one new default queue depth after calling ->sdev_configure
*/
if (!need_alloc && new_shift != sdev->budget_map.shift)
need_alloc = need_free = true;
@@ -240,12 +241,12 @@ static int scsi_realloc_sdev_budget_map(struct scsi_device *sdev,
* and here disk isn't added yet, so freezing is pretty fast
*/
if (need_free) {
- blk_mq_freeze_queue(sdev->request_queue);
+ memflags = blk_mq_freeze_queue(sdev->request_queue);
sb_backup = sdev->budget_map;
}
ret = sbitmap_init_node(&sdev->budget_map,
scsi_device_max_queue_depth(sdev),
- new_shift, GFP_KERNEL,
+ new_shift, GFP_NOIO,
sdev->request_queue->node, false, true);
if (!ret)
sbitmap_resize(&sdev->budget_map, depth);
@@ -256,7 +257,7 @@ static int scsi_realloc_sdev_budget_map(struct scsi_device *sdev,
else
sbitmap_free(&sb_backup);
ret = 0;
- blk_mq_unfreeze_queue(sdev->request_queue);
+ blk_mq_unfreeze_queue(sdev->request_queue, memflags);
}
return ret;
}
@@ -265,7 +266,7 @@ static int scsi_realloc_sdev_budget_map(struct scsi_device *sdev,
* scsi_alloc_sdev - allocate and setup a scsi_Device
* @starget: which target to allocate a &scsi_device for
* @lun: which lun
- * @hostdata: usually NULL and set by ->slave_alloc instead
+ * @hostdata: usually NULL and set by ->sdev_init instead
*
* Description:
* Allocate, initialize for io, and return a pointer to a scsi_Device.
@@ -283,6 +284,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
struct request_queue *q;
int display_failure_msg = 1, ret;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct queue_limits lim;
sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size,
GFP_KERNEL);
@@ -311,11 +313,11 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
sdev->sdev_gendev.parent = get_device(&starget->dev);
sdev->sdev_target = starget;
- /* usually NULL and set by ->slave_alloc instead */
+ /* usually NULL and set by ->sdev_init instead */
sdev->hostdata = hostdata;
/* if the device needs this changing, it may do so in the
- * slave_configure function */
+ * sdev_configure function */
sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED;
/*
@@ -332,7 +334,8 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
sdev->sg_reserved_size = INT_MAX;
- q = blk_mq_init_queue(&sdev->host->tag_set);
+ scsi_init_limits(shost, &lim);
+ q = blk_mq_alloc_queue(&sdev->host->tag_set, &lim, sdev);
if (IS_ERR(q)) {
/* release fn is set up in scsi_sysfs_device_initialise, so
* have to free and put manually here */
@@ -342,8 +345,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
}
kref_get(&sdev->host->tagset_refcnt);
sdev->request_queue = q;
- q->queuedata = sdev;
- __scsi_init_queue(sdev->host, q);
depth = sdev->host->cmd_per_lun ?: 1;
@@ -363,8 +364,8 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
scsi_sysfs_device_initialize(sdev);
- if (shost->hostt->slave_alloc) {
- ret = shost->hostt->slave_alloc(sdev);
+ if (shost->hostt->sdev_init) {
+ ret = shost->hostt->sdev_init(sdev);
if (ret) {
/*
* if LLDD reports slave not present, don't clutter
@@ -412,7 +413,7 @@ static void scsi_target_dev_release(struct device *dev)
put_device(parent);
}
-static struct device_type scsi_target_type = {
+static const struct device_type scsi_target_type = {
.name = "scsi_target",
.release = scsi_target_dev_release,
};
@@ -626,6 +627,7 @@ void scsi_sanitize_inquiry_string(unsigned char *s, int len)
}
EXPORT_SYMBOL(scsi_sanitize_inquiry_string);
+
/**
* scsi_probe_lun - probe a single LUN using a SCSI INQUIRY
* @sdev: scsi_device to probe
@@ -647,10 +649,36 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
int first_inquiry_len, try_inquiry_len, next_inquiry_len;
int response_len = 0;
int pass, count, result, resid;
- struct scsi_sense_hdr sshdr;
+ struct scsi_failure failure_defs[] = {
+ /*
+ * not-ready to ready transition [asc/ascq=0x28/0x0] or
+ * power-on, reset [asc/ascq=0x29/0x0], continue. INQUIRY
+ * should not yield UNIT_ATTENTION but many buggy devices do
+ * so anyway.
+ */
+ {
+ .sense = UNIT_ATTENTION,
+ .asc = 0x28,
+ .result = SAM_STAT_CHECK_CONDITION,
+ },
+ {
+ .sense = UNIT_ATTENTION,
+ .asc = 0x29,
+ .result = SAM_STAT_CHECK_CONDITION,
+ },
+ {
+ .allowed = 1,
+ .result = DID_TIME_OUT << 16,
+ },
+ {}
+ };
+ struct scsi_failures failures = {
+ .total_allowed = 3,
+ .failure_definitions = failure_defs,
+ };
const struct scsi_exec_args exec_args = {
- .sshdr = &sshdr,
.resid = &resid,
+ .failures = &failures,
};
*bflags = 0;
@@ -668,6 +696,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
pass, try_inquiry_len));
/* Each pass gets up to three chances to ignore Unit Attention */
+ scsi_failures_reset_retries(&failures);
+
for (count = 0; count < 3; ++count) {
memset(scsi_cmd, 0, 6);
scsi_cmd[0] = INQUIRY;
@@ -684,22 +714,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
"scsi scan: INQUIRY %s with code 0x%x\n",
result ? "failed" : "successful", result));
- if (result > 0) {
- /*
- * not-ready to ready transition [asc/ascq=0x28/0x0]
- * or power-on, reset [asc/ascq=0x29/0x0], continue.
- * INQUIRY should not yield UNIT_ATTENTION
- * but many buggy devices do so anyway.
- */
- if (scsi_status_is_check_condition(result) &&
- scsi_sense_valid(&sshdr)) {
- if ((sshdr.sense_key == UNIT_ATTENTION) &&
- ((sshdr.asc == 0x28) ||
- (sshdr.asc == 0x29)) &&
- (sshdr.ascq == 0))
- continue;
- }
- } else if (result == 0) {
+ if (result == 0) {
/*
* if nothing was transferred, we try
* again. It's a workaround for some USB
@@ -859,6 +874,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
blist_flags_t *bflags, int async)
{
+ const struct scsi_host_template *hostt = sdev->host->hostt;
+ struct queue_limits lim;
int ret;
/*
@@ -990,19 +1007,6 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
sdev->select_no_atn = 1;
/*
- * Maximum 512 sector transfer length
- * broken RA4x00 Compaq Disk Array
- */
- if (*bflags & BLIST_MAX_512)
- blk_queue_max_hw_sectors(sdev->request_queue, 512);
- /*
- * Max 1024 sector transfer length for targets that report incorrect
- * max/optimal lengths and relied on the old block layer safe default
- */
- else if (*bflags & BLIST_MAX_1024)
- blk_queue_max_hw_sectors(sdev->request_queue, 1024);
-
- /*
* Some devices may not want to have a start command automatically
* issued when a device is added.
*/
@@ -1062,28 +1066,44 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
transport_configure_device(&sdev->sdev_gendev);
- if (sdev->host->hostt->slave_configure) {
- ret = sdev->host->hostt->slave_configure(sdev);
- if (ret) {
- /*
- * if LLDD reports slave not present, don't clutter
- * console with alloc failure messages
- */
- if (ret != -ENXIO) {
- sdev_printk(KERN_ERR, sdev,
- "failed to configure device\n");
- }
- return SCSI_SCAN_NO_RESPONSE;
- }
+ /*
+ * No need to freeze the queue as it isn't reachable to anyone else yet.
+ */
+ lim = queue_limits_start_update(sdev->request_queue);
+ if (*bflags & BLIST_MAX_512)
+ lim.max_hw_sectors = 512;
+ else if (*bflags & BLIST_MAX_1024)
+ lim.max_hw_sectors = 1024;
+ if (hostt->sdev_configure)
+ ret = hostt->sdev_configure(sdev, &lim);
+ if (ret) {
+ queue_limits_cancel_update(sdev->request_queue);
/*
- * The queue_depth is often changed in ->slave_configure.
- * Set up budget map again since memory consumption of
- * the map depends on actual queue depth.
+ * If the LLDD reports device not present, don't clutter the
+ * console with failure messages.
*/
- scsi_realloc_sdev_budget_map(sdev, sdev->queue_depth);
+ if (ret != -ENXIO)
+ sdev_printk(KERN_ERR, sdev,
+ "failed to configure device\n");
+ return SCSI_SCAN_NO_RESPONSE;
}
+ ret = queue_limits_commit_update(sdev->request_queue, &lim);
+ if (ret) {
+ sdev_printk(KERN_ERR, sdev, "failed to apply queue limits.\n");
+ return SCSI_SCAN_NO_RESPONSE;
+ }
+
+ /*
+ * The queue_depth is often changed in ->sdev_configure.
+ *
+ * Set up budget map again since memory consumption of the map depends
+ * on actual queue depth.
+ */
+ if (hostt->sdev_configure)
+ scsi_realloc_sdev_budget_map(sdev, sdev->queue_depth);
+
if (sdev->scsi_level >= SCSI_3)
scsi_attach_vpd(sdev);
@@ -1402,14 +1422,34 @@ static int scsi_report_lun_scan(struct scsi_target *starget, blist_flags_t bflag
unsigned int length;
u64 lun;
unsigned int num_luns;
- unsigned int retries;
int result;
struct scsi_lun *lunp, *lun_data;
- struct scsi_sense_hdr sshdr;
struct scsi_device *sdev;
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+ struct scsi_failure failure_defs[] = {
+ {
+ .sense = UNIT_ATTENTION,
+ .asc = SCMD_FAILURE_ASC_ANY,
+ .ascq = SCMD_FAILURE_ASCQ_ANY,
+ .result = SAM_STAT_CHECK_CONDITION,
+ },
+ /* Fail all CCs except the UA above */
+ {
+ .sense = SCMD_FAILURE_SENSE_ANY,
+ .result = SAM_STAT_CHECK_CONDITION,
+ },
+ /* Retry any other errors not listed above */
+ {
+ .result = SCMD_FAILURE_RESULT_ANY,
+ },
+ {}
+ };
+ struct scsi_failures failures = {
+ .total_allowed = 3,
+ .failure_definitions = failure_defs,
+ };
const struct scsi_exec_args exec_args = {
- .sshdr = &sshdr,
+ .failures = &failures,
};
int ret = 0;
@@ -1480,29 +1520,18 @@ retry:
* should come through as a check condition, and will not generate
* a retry.
*/
- for (retries = 0; retries < 3; retries++) {
- SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
- "scsi scan: Sending REPORT LUNS to (try %d)\n",
- retries));
-
- result = scsi_execute_cmd(sdev, scsi_cmd, REQ_OP_DRV_IN,
- lun_data, length,
- SCSI_REPORT_LUNS_TIMEOUT, 3,
- &exec_args);
+ scsi_failures_reset_retries(&failures);
- SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
- "scsi scan: REPORT LUNS"
- " %s (try %d) result 0x%x\n",
- result ? "failed" : "successful",
- retries, result));
- if (result == 0)
- break;
- else if (scsi_sense_valid(&sshdr)) {
- if (sshdr.sense_key != UNIT_ATTENTION)
- break;
- }
- }
+ SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
+ "scsi scan: Sending REPORT LUNS\n"));
+
+ result = scsi_execute_cmd(sdev, scsi_cmd, REQ_OP_DRV_IN, lun_data,
+ length, SCSI_REPORT_LUNS_TIMEOUT, 3,
+ &exec_args);
+ SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
+ "scsi scan: REPORT LUNS %s result 0x%x\n",
+ result ? "failed" : "successful", result));
if (result) {
/*
* The device probably does not support a REPORT LUN command
@@ -1606,6 +1635,24 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
}
EXPORT_SYMBOL(__scsi_add_device);
+/**
+ * scsi_add_device - creates a new SCSI (LU) instance
+ * @host: the &Scsi_Host instance where the device is located
+ * @channel: target channel number (rarely other than %0)
+ * @target: target id number
+ * @lun: LUN of target device
+ *
+ * Probe for a specific LUN and add it if found.
+ *
+ * Notes: This call is usually performed internally during a SCSI
+ * bus scan when an HBA is added (i.e. scsi_scan_host()). So it
+ * should only be called if the HBA becomes aware of a new SCSI
+ * device (LU) after scsi_scan_host() has completed. If successful
+ * this call can lead to sdev_init() and sdev_configure() callbacks
+ * into the LLD.
+ *
+ * Return: %0 on success or negative error code on failure
+ */
int scsi_add_device(struct Scsi_Host *host, uint channel,
uint target, u64 lun)
{
@@ -1619,6 +1666,40 @@ int scsi_add_device(struct Scsi_Host *host, uint channel,
}
EXPORT_SYMBOL(scsi_add_device);
+int scsi_resume_device(struct scsi_device *sdev)
+{
+ struct device *dev = &sdev->sdev_gendev;
+ int ret = 0;
+
+ device_lock(dev);
+
+ /*
+ * Bail out if the device or its queue are not running. Otherwise,
+ * the rescan may block waiting for commands to be executed, with us
+ * holding the device lock. This can result in a potential deadlock
+ * in the power management core code when system resume is on-going.
+ */
+ if (sdev->sdev_state != SDEV_RUNNING ||
+ blk_queue_pm_only(sdev->request_queue)) {
+ ret = -EWOULDBLOCK;
+ goto unlock;
+ }
+
+ if (dev->driver && try_module_get(dev->driver->owner)) {
+ struct scsi_driver *drv = to_scsi_driver(dev->driver);
+
+ if (drv->resume)
+ ret = drv->resume(dev);
+ module_put(dev->driver->owner);
+ }
+
+unlock:
+ device_unlock(dev);
+
+ return ret;
+}
+EXPORT_SYMBOL(scsi_resume_device);
+
int scsi_rescan_device(struct scsi_device *sdev)
{
struct device *dev = &sdev->sdev_gendev;
@@ -1963,6 +2044,8 @@ static void do_scan_async(void *_data, async_cookie_t c)
/**
* scsi_scan_host - scan the given adapter
* @shost: adapter to scan
+ *
+ * Notes: Should be called after scsi_add_host()
**/
void scsi_scan_host(struct Scsi_Host *shost)
{