162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * scsi_sysfs.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * SCSI sysfs interface routines.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Created to pull SCSI mid layer sysfs routines into one file.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/slab.h>
1262306a36Sopenharmony_ci#include <linux/init.h>
1362306a36Sopenharmony_ci#include <linux/blkdev.h>
1462306a36Sopenharmony_ci#include <linux/device.h>
1562306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1662306a36Sopenharmony_ci#include <linux/bsg.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <scsi/scsi.h>
1962306a36Sopenharmony_ci#include <scsi/scsi_device.h>
2062306a36Sopenharmony_ci#include <scsi/scsi_host.h>
2162306a36Sopenharmony_ci#include <scsi/scsi_tcq.h>
2262306a36Sopenharmony_ci#include <scsi/scsi_dh.h>
2362306a36Sopenharmony_ci#include <scsi/scsi_transport.h>
2462306a36Sopenharmony_ci#include <scsi/scsi_driver.h>
2562306a36Sopenharmony_ci#include <scsi/scsi_devinfo.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include "scsi_priv.h"
2862306a36Sopenharmony_ci#include "scsi_logging.h"
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic struct device_type scsi_dev_type;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic const struct {
3362306a36Sopenharmony_ci	enum scsi_device_state	value;
3462306a36Sopenharmony_ci	char			*name;
3562306a36Sopenharmony_ci} sdev_states[] = {
3662306a36Sopenharmony_ci	{ SDEV_CREATED, "created" },
3762306a36Sopenharmony_ci	{ SDEV_RUNNING, "running" },
3862306a36Sopenharmony_ci	{ SDEV_CANCEL, "cancel" },
3962306a36Sopenharmony_ci	{ SDEV_DEL, "deleted" },
4062306a36Sopenharmony_ci	{ SDEV_QUIESCE, "quiesce" },
4162306a36Sopenharmony_ci	{ SDEV_OFFLINE,	"offline" },
4262306a36Sopenharmony_ci	{ SDEV_TRANSPORT_OFFLINE, "transport-offline" },
4362306a36Sopenharmony_ci	{ SDEV_BLOCK,	"blocked" },
4462306a36Sopenharmony_ci	{ SDEV_CREATED_BLOCK, "created-blocked" },
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ciconst char *scsi_device_state_name(enum scsi_device_state state)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	int i;
5062306a36Sopenharmony_ci	char *name = NULL;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
5362306a36Sopenharmony_ci		if (sdev_states[i].value == state) {
5462306a36Sopenharmony_ci			name = sdev_states[i].name;
5562306a36Sopenharmony_ci			break;
5662306a36Sopenharmony_ci		}
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci	return name;
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic const struct {
6262306a36Sopenharmony_ci	enum scsi_host_state	value;
6362306a36Sopenharmony_ci	char			*name;
6462306a36Sopenharmony_ci} shost_states[] = {
6562306a36Sopenharmony_ci	{ SHOST_CREATED, "created" },
6662306a36Sopenharmony_ci	{ SHOST_RUNNING, "running" },
6762306a36Sopenharmony_ci	{ SHOST_CANCEL, "cancel" },
6862306a36Sopenharmony_ci	{ SHOST_DEL, "deleted" },
6962306a36Sopenharmony_ci	{ SHOST_RECOVERY, "recovery" },
7062306a36Sopenharmony_ci	{ SHOST_CANCEL_RECOVERY, "cancel/recovery" },
7162306a36Sopenharmony_ci	{ SHOST_DEL_RECOVERY, "deleted/recovery", },
7262306a36Sopenharmony_ci};
7362306a36Sopenharmony_ciconst char *scsi_host_state_name(enum scsi_host_state state)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	int i;
7662306a36Sopenharmony_ci	char *name = NULL;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(shost_states); i++) {
7962306a36Sopenharmony_ci		if (shost_states[i].value == state) {
8062306a36Sopenharmony_ci			name = shost_states[i].name;
8162306a36Sopenharmony_ci			break;
8262306a36Sopenharmony_ci		}
8362306a36Sopenharmony_ci	}
8462306a36Sopenharmony_ci	return name;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#ifdef CONFIG_SCSI_DH
8862306a36Sopenharmony_cistatic const struct {
8962306a36Sopenharmony_ci	unsigned char	value;
9062306a36Sopenharmony_ci	char		*name;
9162306a36Sopenharmony_ci} sdev_access_states[] = {
9262306a36Sopenharmony_ci	{ SCSI_ACCESS_STATE_OPTIMAL, "active/optimized" },
9362306a36Sopenharmony_ci	{ SCSI_ACCESS_STATE_ACTIVE, "active/non-optimized" },
9462306a36Sopenharmony_ci	{ SCSI_ACCESS_STATE_STANDBY, "standby" },
9562306a36Sopenharmony_ci	{ SCSI_ACCESS_STATE_UNAVAILABLE, "unavailable" },
9662306a36Sopenharmony_ci	{ SCSI_ACCESS_STATE_LBA, "lba-dependent" },
9762306a36Sopenharmony_ci	{ SCSI_ACCESS_STATE_OFFLINE, "offline" },
9862306a36Sopenharmony_ci	{ SCSI_ACCESS_STATE_TRANSITIONING, "transitioning" },
9962306a36Sopenharmony_ci};
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic const char *scsi_access_state_name(unsigned char state)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	int i;
10462306a36Sopenharmony_ci	char *name = NULL;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(sdev_access_states); i++) {
10762306a36Sopenharmony_ci		if (sdev_access_states[i].value == state) {
10862306a36Sopenharmony_ci			name = sdev_access_states[i].name;
10962306a36Sopenharmony_ci			break;
11062306a36Sopenharmony_ci		}
11162306a36Sopenharmony_ci	}
11262306a36Sopenharmony_ci	return name;
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci#endif
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic int check_set(unsigned long long *val, char *src)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	char *last;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	if (strcmp(src, "-") == 0) {
12162306a36Sopenharmony_ci		*val = SCAN_WILD_CARD;
12262306a36Sopenharmony_ci	} else {
12362306a36Sopenharmony_ci		/*
12462306a36Sopenharmony_ci		 * Doesn't check for int overflow
12562306a36Sopenharmony_ci		 */
12662306a36Sopenharmony_ci		*val = simple_strtoull(src, &last, 0);
12762306a36Sopenharmony_ci		if (*last != '\0')
12862306a36Sopenharmony_ci			return 1;
12962306a36Sopenharmony_ci	}
13062306a36Sopenharmony_ci	return 0;
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic int scsi_scan(struct Scsi_Host *shost, const char *str)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	char s1[15], s2[15], s3[17], junk;
13662306a36Sopenharmony_ci	unsigned long long channel, id, lun;
13762306a36Sopenharmony_ci	int res;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	res = sscanf(str, "%10s %10s %16s %c", s1, s2, s3, &junk);
14062306a36Sopenharmony_ci	if (res != 3)
14162306a36Sopenharmony_ci		return -EINVAL;
14262306a36Sopenharmony_ci	if (check_set(&channel, s1))
14362306a36Sopenharmony_ci		return -EINVAL;
14462306a36Sopenharmony_ci	if (check_set(&id, s2))
14562306a36Sopenharmony_ci		return -EINVAL;
14662306a36Sopenharmony_ci	if (check_set(&lun, s3))
14762306a36Sopenharmony_ci		return -EINVAL;
14862306a36Sopenharmony_ci	if (shost->transportt->user_scan)
14962306a36Sopenharmony_ci		res = shost->transportt->user_scan(shost, channel, id, lun);
15062306a36Sopenharmony_ci	else
15162306a36Sopenharmony_ci		res = scsi_scan_host_selected(shost, channel, id, lun,
15262306a36Sopenharmony_ci					      SCSI_SCAN_MANUAL);
15362306a36Sopenharmony_ci	return res;
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci/*
15762306a36Sopenharmony_ci * shost_show_function: macro to create an attr function that can be used to
15862306a36Sopenharmony_ci * show a non-bit field.
15962306a36Sopenharmony_ci */
16062306a36Sopenharmony_ci#define shost_show_function(name, field, format_string)			\
16162306a36Sopenharmony_cistatic ssize_t								\
16262306a36Sopenharmony_cishow_##name (struct device *dev, struct device_attribute *attr, 	\
16362306a36Sopenharmony_ci	     char *buf)							\
16462306a36Sopenharmony_ci{									\
16562306a36Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(dev);			\
16662306a36Sopenharmony_ci	return snprintf (buf, 20, format_string, shost->field);		\
16762306a36Sopenharmony_ci}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci/*
17062306a36Sopenharmony_ci * shost_rd_attr: macro to create a function and attribute variable for a
17162306a36Sopenharmony_ci * read only field.
17262306a36Sopenharmony_ci */
17362306a36Sopenharmony_ci#define shost_rd_attr2(name, field, format_string)			\
17462306a36Sopenharmony_ci	shost_show_function(name, field, format_string)			\
17562306a36Sopenharmony_cistatic DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci#define shost_rd_attr(field, format_string) \
17862306a36Sopenharmony_cishost_rd_attr2(field, field, format_string)
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci/*
18162306a36Sopenharmony_ci * Create the actual show/store functions and data structures.
18262306a36Sopenharmony_ci */
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic ssize_t
18562306a36Sopenharmony_cistore_scan(struct device *dev, struct device_attribute *attr,
18662306a36Sopenharmony_ci	   const char *buf, size_t count)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(dev);
18962306a36Sopenharmony_ci	int res;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	res = scsi_scan(shost, buf);
19262306a36Sopenharmony_ci	if (res == 0)
19362306a36Sopenharmony_ci		res = count;
19462306a36Sopenharmony_ci	return res;
19562306a36Sopenharmony_ci};
19662306a36Sopenharmony_cistatic DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic ssize_t
19962306a36Sopenharmony_cistore_shost_state(struct device *dev, struct device_attribute *attr,
20062306a36Sopenharmony_ci		  const char *buf, size_t count)
20162306a36Sopenharmony_ci{
20262306a36Sopenharmony_ci	int i;
20362306a36Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(dev);
20462306a36Sopenharmony_ci	enum scsi_host_state state = 0;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(shost_states); i++) {
20762306a36Sopenharmony_ci		const int len = strlen(shost_states[i].name);
20862306a36Sopenharmony_ci		if (strncmp(shost_states[i].name, buf, len) == 0 &&
20962306a36Sopenharmony_ci		   buf[len] == '\n') {
21062306a36Sopenharmony_ci			state = shost_states[i].value;
21162306a36Sopenharmony_ci			break;
21262306a36Sopenharmony_ci		}
21362306a36Sopenharmony_ci	}
21462306a36Sopenharmony_ci	if (!state)
21562306a36Sopenharmony_ci		return -EINVAL;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	if (scsi_host_set_state(shost, state))
21862306a36Sopenharmony_ci		return -EINVAL;
21962306a36Sopenharmony_ci	return count;
22062306a36Sopenharmony_ci}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistatic ssize_t
22362306a36Sopenharmony_cishow_shost_state(struct device *dev, struct device_attribute *attr, char *buf)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(dev);
22662306a36Sopenharmony_ci	const char *name = scsi_host_state_name(shost->shost_state);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	if (!name)
22962306a36Sopenharmony_ci		return -EINVAL;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	return snprintf(buf, 20, "%s\n", name);
23262306a36Sopenharmony_ci}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci/* DEVICE_ATTR(state) clashes with dev_attr_state for sdev */
23562306a36Sopenharmony_cistatic struct device_attribute dev_attr_hstate =
23662306a36Sopenharmony_ci	__ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic ssize_t
23962306a36Sopenharmony_cishow_shost_mode(unsigned int mode, char *buf)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	ssize_t len = 0;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	if (mode & MODE_INITIATOR)
24462306a36Sopenharmony_ci		len = sprintf(buf, "%s", "Initiator");
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	if (mode & MODE_TARGET)
24762306a36Sopenharmony_ci		len += sprintf(buf + len, "%s%s", len ? ", " : "", "Target");
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	len += sprintf(buf + len, "\n");
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	return len;
25262306a36Sopenharmony_ci}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_cistatic ssize_t
25562306a36Sopenharmony_cishow_shost_supported_mode(struct device *dev, struct device_attribute *attr,
25662306a36Sopenharmony_ci			  char *buf)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(dev);
25962306a36Sopenharmony_ci	unsigned int supported_mode = shost->hostt->supported_mode;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	if (supported_mode == MODE_UNKNOWN)
26262306a36Sopenharmony_ci		/* by default this should be initiator */
26362306a36Sopenharmony_ci		supported_mode = MODE_INITIATOR;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	return show_shost_mode(supported_mode, buf);
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cistatic DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistatic ssize_t
27162306a36Sopenharmony_cishow_shost_active_mode(struct device *dev,
27262306a36Sopenharmony_ci		       struct device_attribute *attr, char *buf)
27362306a36Sopenharmony_ci{
27462306a36Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(dev);
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	if (shost->active_mode == MODE_UNKNOWN)
27762306a36Sopenharmony_ci		return snprintf(buf, 20, "unknown\n");
27862306a36Sopenharmony_ci	else
27962306a36Sopenharmony_ci		return show_shost_mode(shost->active_mode, buf);
28062306a36Sopenharmony_ci}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_cistatic DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic int check_reset_type(const char *str)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	if (sysfs_streq(str, "adapter"))
28762306a36Sopenharmony_ci		return SCSI_ADAPTER_RESET;
28862306a36Sopenharmony_ci	else if (sysfs_streq(str, "firmware"))
28962306a36Sopenharmony_ci		return SCSI_FIRMWARE_RESET;
29062306a36Sopenharmony_ci	else
29162306a36Sopenharmony_ci		return 0;
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_cistatic ssize_t
29562306a36Sopenharmony_cistore_host_reset(struct device *dev, struct device_attribute *attr,
29662306a36Sopenharmony_ci		const char *buf, size_t count)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(dev);
29962306a36Sopenharmony_ci	const struct scsi_host_template *sht = shost->hostt;
30062306a36Sopenharmony_ci	int ret = -EINVAL;
30162306a36Sopenharmony_ci	int type;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	type = check_reset_type(buf);
30462306a36Sopenharmony_ci	if (!type)
30562306a36Sopenharmony_ci		goto exit_store_host_reset;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	if (sht->host_reset)
30862306a36Sopenharmony_ci		ret = sht->host_reset(shost, type);
30962306a36Sopenharmony_ci	else
31062306a36Sopenharmony_ci		ret = -EOPNOTSUPP;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ciexit_store_host_reset:
31362306a36Sopenharmony_ci	if (ret == 0)
31462306a36Sopenharmony_ci		ret = count;
31562306a36Sopenharmony_ci	return ret;
31662306a36Sopenharmony_ci}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_cistatic DEVICE_ATTR(host_reset, S_IWUSR, NULL, store_host_reset);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cistatic ssize_t
32162306a36Sopenharmony_cishow_shost_eh_deadline(struct device *dev,
32262306a36Sopenharmony_ci		      struct device_attribute *attr, char *buf)
32362306a36Sopenharmony_ci{
32462306a36Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(dev);
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	if (shost->eh_deadline == -1)
32762306a36Sopenharmony_ci		return snprintf(buf, strlen("off") + 2, "off\n");
32862306a36Sopenharmony_ci	return sprintf(buf, "%u\n", shost->eh_deadline / HZ);
32962306a36Sopenharmony_ci}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_cistatic ssize_t
33262306a36Sopenharmony_cistore_shost_eh_deadline(struct device *dev, struct device_attribute *attr,
33362306a36Sopenharmony_ci		const char *buf, size_t count)
33462306a36Sopenharmony_ci{
33562306a36Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(dev);
33662306a36Sopenharmony_ci	int ret = -EINVAL;
33762306a36Sopenharmony_ci	unsigned long deadline, flags;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	if (shost->transportt &&
34062306a36Sopenharmony_ci	    (shost->transportt->eh_strategy_handler ||
34162306a36Sopenharmony_ci	     !shost->hostt->eh_host_reset_handler))
34262306a36Sopenharmony_ci		return ret;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	if (!strncmp(buf, "off", strlen("off")))
34562306a36Sopenharmony_ci		deadline = -1;
34662306a36Sopenharmony_ci	else {
34762306a36Sopenharmony_ci		ret = kstrtoul(buf, 10, &deadline);
34862306a36Sopenharmony_ci		if (ret)
34962306a36Sopenharmony_ci			return ret;
35062306a36Sopenharmony_ci		if (deadline * HZ > UINT_MAX)
35162306a36Sopenharmony_ci			return -EINVAL;
35262306a36Sopenharmony_ci	}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	spin_lock_irqsave(shost->host_lock, flags);
35562306a36Sopenharmony_ci	if (scsi_host_in_recovery(shost))
35662306a36Sopenharmony_ci		ret = -EBUSY;
35762306a36Sopenharmony_ci	else {
35862306a36Sopenharmony_ci		if (deadline == -1)
35962306a36Sopenharmony_ci			shost->eh_deadline = -1;
36062306a36Sopenharmony_ci		else
36162306a36Sopenharmony_ci			shost->eh_deadline = deadline * HZ;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci		ret = count;
36462306a36Sopenharmony_ci	}
36562306a36Sopenharmony_ci	spin_unlock_irqrestore(shost->host_lock, flags);
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	return ret;
36862306a36Sopenharmony_ci}
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_cistatic DEVICE_ATTR(eh_deadline, S_IRUGO | S_IWUSR, show_shost_eh_deadline, store_shost_eh_deadline);
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_cishost_rd_attr(unique_id, "%u\n");
37362306a36Sopenharmony_cishost_rd_attr(cmd_per_lun, "%hd\n");
37462306a36Sopenharmony_cishost_rd_attr(can_queue, "%d\n");
37562306a36Sopenharmony_cishost_rd_attr(sg_tablesize, "%hu\n");
37662306a36Sopenharmony_cishost_rd_attr(sg_prot_tablesize, "%hu\n");
37762306a36Sopenharmony_cishost_rd_attr(prot_capabilities, "%u\n");
37862306a36Sopenharmony_cishost_rd_attr(prot_guard_type, "%hd\n");
37962306a36Sopenharmony_cishost_rd_attr2(proc_name, hostt->proc_name, "%s\n");
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_cistatic ssize_t
38262306a36Sopenharmony_cishow_host_busy(struct device *dev, struct device_attribute *attr, char *buf)
38362306a36Sopenharmony_ci{
38462306a36Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(dev);
38562306a36Sopenharmony_ci	return snprintf(buf, 20, "%d\n", scsi_host_busy(shost));
38662306a36Sopenharmony_ci}
38762306a36Sopenharmony_cistatic DEVICE_ATTR(host_busy, S_IRUGO, show_host_busy, NULL);
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_cistatic ssize_t
39062306a36Sopenharmony_cishow_use_blk_mq(struct device *dev, struct device_attribute *attr, char *buf)
39162306a36Sopenharmony_ci{
39262306a36Sopenharmony_ci	return sprintf(buf, "1\n");
39362306a36Sopenharmony_ci}
39462306a36Sopenharmony_cistatic DEVICE_ATTR(use_blk_mq, S_IRUGO, show_use_blk_mq, NULL);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_cistatic ssize_t
39762306a36Sopenharmony_cishow_nr_hw_queues(struct device *dev, struct device_attribute *attr, char *buf)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(dev);
40062306a36Sopenharmony_ci	struct blk_mq_tag_set *tag_set = &shost->tag_set;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	return snprintf(buf, 20, "%d\n", tag_set->nr_hw_queues);
40362306a36Sopenharmony_ci}
40462306a36Sopenharmony_cistatic DEVICE_ATTR(nr_hw_queues, S_IRUGO, show_nr_hw_queues, NULL);
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_cistatic struct attribute *scsi_sysfs_shost_attrs[] = {
40762306a36Sopenharmony_ci	&dev_attr_use_blk_mq.attr,
40862306a36Sopenharmony_ci	&dev_attr_unique_id.attr,
40962306a36Sopenharmony_ci	&dev_attr_host_busy.attr,
41062306a36Sopenharmony_ci	&dev_attr_cmd_per_lun.attr,
41162306a36Sopenharmony_ci	&dev_attr_can_queue.attr,
41262306a36Sopenharmony_ci	&dev_attr_sg_tablesize.attr,
41362306a36Sopenharmony_ci	&dev_attr_sg_prot_tablesize.attr,
41462306a36Sopenharmony_ci	&dev_attr_proc_name.attr,
41562306a36Sopenharmony_ci	&dev_attr_scan.attr,
41662306a36Sopenharmony_ci	&dev_attr_hstate.attr,
41762306a36Sopenharmony_ci	&dev_attr_supported_mode.attr,
41862306a36Sopenharmony_ci	&dev_attr_active_mode.attr,
41962306a36Sopenharmony_ci	&dev_attr_prot_capabilities.attr,
42062306a36Sopenharmony_ci	&dev_attr_prot_guard_type.attr,
42162306a36Sopenharmony_ci	&dev_attr_host_reset.attr,
42262306a36Sopenharmony_ci	&dev_attr_eh_deadline.attr,
42362306a36Sopenharmony_ci	&dev_attr_nr_hw_queues.attr,
42462306a36Sopenharmony_ci	NULL
42562306a36Sopenharmony_ci};
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_cistatic const struct attribute_group scsi_shost_attr_group = {
42862306a36Sopenharmony_ci	.attrs =	scsi_sysfs_shost_attrs,
42962306a36Sopenharmony_ci};
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ciconst struct attribute_group *scsi_shost_groups[] = {
43262306a36Sopenharmony_ci	&scsi_shost_attr_group,
43362306a36Sopenharmony_ci	NULL
43462306a36Sopenharmony_ci};
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_cistatic void scsi_device_cls_release(struct device *class_dev)
43762306a36Sopenharmony_ci{
43862306a36Sopenharmony_ci	struct scsi_device *sdev;
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	sdev = class_to_sdev(class_dev);
44162306a36Sopenharmony_ci	put_device(&sdev->sdev_gendev);
44262306a36Sopenharmony_ci}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_cistatic void scsi_device_dev_release(struct device *dev)
44562306a36Sopenharmony_ci{
44662306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
44762306a36Sopenharmony_ci	struct device *parent;
44862306a36Sopenharmony_ci	struct list_head *this, *tmp;
44962306a36Sopenharmony_ci	struct scsi_vpd *vpd_pg80 = NULL, *vpd_pg83 = NULL;
45062306a36Sopenharmony_ci	struct scsi_vpd *vpd_pg0 = NULL, *vpd_pg89 = NULL;
45162306a36Sopenharmony_ci	struct scsi_vpd *vpd_pgb0 = NULL, *vpd_pgb1 = NULL, *vpd_pgb2 = NULL;
45262306a36Sopenharmony_ci	unsigned long flags;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	might_sleep();
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	scsi_dh_release_device(sdev);
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	parent = sdev->sdev_gendev.parent;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	spin_lock_irqsave(sdev->host->host_lock, flags);
46162306a36Sopenharmony_ci	list_del(&sdev->siblings);
46262306a36Sopenharmony_ci	list_del(&sdev->same_target_siblings);
46362306a36Sopenharmony_ci	list_del(&sdev->starved_entry);
46462306a36Sopenharmony_ci	spin_unlock_irqrestore(sdev->host->host_lock, flags);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	cancel_work_sync(&sdev->event_work);
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	list_for_each_safe(this, tmp, &sdev->event_list) {
46962306a36Sopenharmony_ci		struct scsi_event *evt;
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci		evt = list_entry(this, struct scsi_event, node);
47262306a36Sopenharmony_ci		list_del(&evt->node);
47362306a36Sopenharmony_ci		kfree(evt);
47462306a36Sopenharmony_ci	}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	blk_put_queue(sdev->request_queue);
47762306a36Sopenharmony_ci	/* NULL queue means the device can't be used */
47862306a36Sopenharmony_ci	sdev->request_queue = NULL;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	sbitmap_free(&sdev->budget_map);
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	mutex_lock(&sdev->inquiry_mutex);
48362306a36Sopenharmony_ci	vpd_pg0 = rcu_replace_pointer(sdev->vpd_pg0, vpd_pg0,
48462306a36Sopenharmony_ci				       lockdep_is_held(&sdev->inquiry_mutex));
48562306a36Sopenharmony_ci	vpd_pg80 = rcu_replace_pointer(sdev->vpd_pg80, vpd_pg80,
48662306a36Sopenharmony_ci				       lockdep_is_held(&sdev->inquiry_mutex));
48762306a36Sopenharmony_ci	vpd_pg83 = rcu_replace_pointer(sdev->vpd_pg83, vpd_pg83,
48862306a36Sopenharmony_ci				       lockdep_is_held(&sdev->inquiry_mutex));
48962306a36Sopenharmony_ci	vpd_pg89 = rcu_replace_pointer(sdev->vpd_pg89, vpd_pg89,
49062306a36Sopenharmony_ci				       lockdep_is_held(&sdev->inquiry_mutex));
49162306a36Sopenharmony_ci	vpd_pgb0 = rcu_replace_pointer(sdev->vpd_pgb0, vpd_pgb0,
49262306a36Sopenharmony_ci				       lockdep_is_held(&sdev->inquiry_mutex));
49362306a36Sopenharmony_ci	vpd_pgb1 = rcu_replace_pointer(sdev->vpd_pgb1, vpd_pgb1,
49462306a36Sopenharmony_ci				       lockdep_is_held(&sdev->inquiry_mutex));
49562306a36Sopenharmony_ci	vpd_pgb2 = rcu_replace_pointer(sdev->vpd_pgb2, vpd_pgb2,
49662306a36Sopenharmony_ci				       lockdep_is_held(&sdev->inquiry_mutex));
49762306a36Sopenharmony_ci	mutex_unlock(&sdev->inquiry_mutex);
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	if (vpd_pg0)
50062306a36Sopenharmony_ci		kfree_rcu(vpd_pg0, rcu);
50162306a36Sopenharmony_ci	if (vpd_pg83)
50262306a36Sopenharmony_ci		kfree_rcu(vpd_pg83, rcu);
50362306a36Sopenharmony_ci	if (vpd_pg80)
50462306a36Sopenharmony_ci		kfree_rcu(vpd_pg80, rcu);
50562306a36Sopenharmony_ci	if (vpd_pg89)
50662306a36Sopenharmony_ci		kfree_rcu(vpd_pg89, rcu);
50762306a36Sopenharmony_ci	if (vpd_pgb0)
50862306a36Sopenharmony_ci		kfree_rcu(vpd_pgb0, rcu);
50962306a36Sopenharmony_ci	if (vpd_pgb1)
51062306a36Sopenharmony_ci		kfree_rcu(vpd_pgb1, rcu);
51162306a36Sopenharmony_ci	if (vpd_pgb2)
51262306a36Sopenharmony_ci		kfree_rcu(vpd_pgb2, rcu);
51362306a36Sopenharmony_ci	kfree(sdev->inquiry);
51462306a36Sopenharmony_ci	kfree(sdev);
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	if (parent)
51762306a36Sopenharmony_ci		put_device(parent);
51862306a36Sopenharmony_ci}
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_cistatic struct class sdev_class = {
52162306a36Sopenharmony_ci	.name		= "scsi_device",
52262306a36Sopenharmony_ci	.dev_release	= scsi_device_cls_release,
52362306a36Sopenharmony_ci};
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci/* all probing is done in the individual ->probe routines */
52662306a36Sopenharmony_cistatic int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
52762306a36Sopenharmony_ci{
52862306a36Sopenharmony_ci	struct scsi_device *sdp;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	if (dev->type != &scsi_dev_type)
53162306a36Sopenharmony_ci		return 0;
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	sdp = to_scsi_device(dev);
53462306a36Sopenharmony_ci	if (sdp->no_uld_attach)
53562306a36Sopenharmony_ci		return 0;
53662306a36Sopenharmony_ci	return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
53762306a36Sopenharmony_ci}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_cistatic int scsi_bus_uevent(const struct device *dev, struct kobj_uevent_env *env)
54062306a36Sopenharmony_ci{
54162306a36Sopenharmony_ci	const struct scsi_device *sdev;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	if (dev->type != &scsi_dev_type)
54462306a36Sopenharmony_ci		return 0;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	sdev = to_scsi_device(dev);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
54962306a36Sopenharmony_ci	return 0;
55062306a36Sopenharmony_ci}
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_cistruct bus_type scsi_bus_type = {
55362306a36Sopenharmony_ci        .name		= "scsi",
55462306a36Sopenharmony_ci        .match		= scsi_bus_match,
55562306a36Sopenharmony_ci	.uevent		= scsi_bus_uevent,
55662306a36Sopenharmony_ci#ifdef CONFIG_PM
55762306a36Sopenharmony_ci	.pm		= &scsi_bus_pm_ops,
55862306a36Sopenharmony_ci#endif
55962306a36Sopenharmony_ci};
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ciint scsi_sysfs_register(void)
56262306a36Sopenharmony_ci{
56362306a36Sopenharmony_ci	int error;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	error = bus_register(&scsi_bus_type);
56662306a36Sopenharmony_ci	if (!error) {
56762306a36Sopenharmony_ci		error = class_register(&sdev_class);
56862306a36Sopenharmony_ci		if (error)
56962306a36Sopenharmony_ci			bus_unregister(&scsi_bus_type);
57062306a36Sopenharmony_ci	}
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	return error;
57362306a36Sopenharmony_ci}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_civoid scsi_sysfs_unregister(void)
57662306a36Sopenharmony_ci{
57762306a36Sopenharmony_ci	class_unregister(&sdev_class);
57862306a36Sopenharmony_ci	bus_unregister(&scsi_bus_type);
57962306a36Sopenharmony_ci}
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci/*
58262306a36Sopenharmony_ci * sdev_show_function: macro to create an attr function that can be used to
58362306a36Sopenharmony_ci * show a non-bit field.
58462306a36Sopenharmony_ci */
58562306a36Sopenharmony_ci#define sdev_show_function(field, format_string)				\
58662306a36Sopenharmony_cistatic ssize_t								\
58762306a36Sopenharmony_cisdev_show_##field (struct device *dev, struct device_attribute *attr,	\
58862306a36Sopenharmony_ci		   char *buf)						\
58962306a36Sopenharmony_ci{									\
59062306a36Sopenharmony_ci	struct scsi_device *sdev;					\
59162306a36Sopenharmony_ci	sdev = to_scsi_device(dev);					\
59262306a36Sopenharmony_ci	return snprintf (buf, 20, format_string, sdev->field);		\
59362306a36Sopenharmony_ci}									\
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci/*
59662306a36Sopenharmony_ci * sdev_rd_attr: macro to create a function and attribute variable for a
59762306a36Sopenharmony_ci * read only field.
59862306a36Sopenharmony_ci */
59962306a36Sopenharmony_ci#define sdev_rd_attr(field, format_string)				\
60062306a36Sopenharmony_ci	sdev_show_function(field, format_string)			\
60162306a36Sopenharmony_cistatic DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL);
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci/*
60562306a36Sopenharmony_ci * sdev_rw_attr: create a function and attribute variable for a
60662306a36Sopenharmony_ci * read/write field.
60762306a36Sopenharmony_ci */
60862306a36Sopenharmony_ci#define sdev_rw_attr(field, format_string)				\
60962306a36Sopenharmony_ci	sdev_show_function(field, format_string)				\
61062306a36Sopenharmony_ci									\
61162306a36Sopenharmony_cistatic ssize_t								\
61262306a36Sopenharmony_cisdev_store_##field (struct device *dev, struct device_attribute *attr,	\
61362306a36Sopenharmony_ci		    const char *buf, size_t count)			\
61462306a36Sopenharmony_ci{									\
61562306a36Sopenharmony_ci	struct scsi_device *sdev;					\
61662306a36Sopenharmony_ci	sdev = to_scsi_device(dev);					\
61762306a36Sopenharmony_ci	sscanf (buf, format_string, &sdev->field);			\
61862306a36Sopenharmony_ci	return count;							\
61962306a36Sopenharmony_ci}									\
62062306a36Sopenharmony_cistatic DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci/* Currently we don't export bit fields, but we might in future,
62362306a36Sopenharmony_ci * so leave this code in */
62462306a36Sopenharmony_ci#if 0
62562306a36Sopenharmony_ci/*
62662306a36Sopenharmony_ci * sdev_rd_attr: create a function and attribute variable for a
62762306a36Sopenharmony_ci * read/write bit field.
62862306a36Sopenharmony_ci */
62962306a36Sopenharmony_ci#define sdev_rw_attr_bit(field)						\
63062306a36Sopenharmony_ci	sdev_show_function(field, "%d\n")					\
63162306a36Sopenharmony_ci									\
63262306a36Sopenharmony_cistatic ssize_t								\
63362306a36Sopenharmony_cisdev_store_##field (struct device *dev, struct device_attribute *attr,	\
63462306a36Sopenharmony_ci		    const char *buf, size_t count)			\
63562306a36Sopenharmony_ci{									\
63662306a36Sopenharmony_ci	int ret;							\
63762306a36Sopenharmony_ci	struct scsi_device *sdev;					\
63862306a36Sopenharmony_ci	ret = scsi_sdev_check_buf_bit(buf);				\
63962306a36Sopenharmony_ci	if (ret >= 0)	{						\
64062306a36Sopenharmony_ci		sdev = to_scsi_device(dev);				\
64162306a36Sopenharmony_ci		sdev->field = ret;					\
64262306a36Sopenharmony_ci		ret = count;						\
64362306a36Sopenharmony_ci	}								\
64462306a36Sopenharmony_ci	return ret;							\
64562306a36Sopenharmony_ci}									\
64662306a36Sopenharmony_cistatic DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci/*
64962306a36Sopenharmony_ci * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
65062306a36Sopenharmony_ci * else return -EINVAL.
65162306a36Sopenharmony_ci */
65262306a36Sopenharmony_cistatic int scsi_sdev_check_buf_bit(const char *buf)
65362306a36Sopenharmony_ci{
65462306a36Sopenharmony_ci	if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
65562306a36Sopenharmony_ci		if (buf[0] == '1')
65662306a36Sopenharmony_ci			return 1;
65762306a36Sopenharmony_ci		else if (buf[0] == '0')
65862306a36Sopenharmony_ci			return 0;
65962306a36Sopenharmony_ci		else
66062306a36Sopenharmony_ci			return -EINVAL;
66162306a36Sopenharmony_ci	} else
66262306a36Sopenharmony_ci		return -EINVAL;
66362306a36Sopenharmony_ci}
66462306a36Sopenharmony_ci#endif
66562306a36Sopenharmony_ci/*
66662306a36Sopenharmony_ci * Create the actual show/store functions and data structures.
66762306a36Sopenharmony_ci */
66862306a36Sopenharmony_cisdev_rd_attr (type, "%d\n");
66962306a36Sopenharmony_cisdev_rd_attr (scsi_level, "%d\n");
67062306a36Sopenharmony_cisdev_rd_attr (vendor, "%.8s\n");
67162306a36Sopenharmony_cisdev_rd_attr (model, "%.16s\n");
67262306a36Sopenharmony_cisdev_rd_attr (rev, "%.4s\n");
67362306a36Sopenharmony_cisdev_rd_attr (cdl_supported, "%d\n");
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_cistatic ssize_t
67662306a36Sopenharmony_cisdev_show_device_busy(struct device *dev, struct device_attribute *attr,
67762306a36Sopenharmony_ci		char *buf)
67862306a36Sopenharmony_ci{
67962306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
68062306a36Sopenharmony_ci	return snprintf(buf, 20, "%d\n", scsi_device_busy(sdev));
68162306a36Sopenharmony_ci}
68262306a36Sopenharmony_cistatic DEVICE_ATTR(device_busy, S_IRUGO, sdev_show_device_busy, NULL);
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_cistatic ssize_t
68562306a36Sopenharmony_cisdev_show_device_blocked(struct device *dev, struct device_attribute *attr,
68662306a36Sopenharmony_ci		char *buf)
68762306a36Sopenharmony_ci{
68862306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
68962306a36Sopenharmony_ci	return snprintf(buf, 20, "%d\n", atomic_read(&sdev->device_blocked));
69062306a36Sopenharmony_ci}
69162306a36Sopenharmony_cistatic DEVICE_ATTR(device_blocked, S_IRUGO, sdev_show_device_blocked, NULL);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci/*
69462306a36Sopenharmony_ci * TODO: can we make these symlinks to the block layer ones?
69562306a36Sopenharmony_ci */
69662306a36Sopenharmony_cistatic ssize_t
69762306a36Sopenharmony_cisdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf)
69862306a36Sopenharmony_ci{
69962306a36Sopenharmony_ci	struct scsi_device *sdev;
70062306a36Sopenharmony_ci	sdev = to_scsi_device(dev);
70162306a36Sopenharmony_ci	return snprintf(buf, 20, "%d\n", sdev->request_queue->rq_timeout / HZ);
70262306a36Sopenharmony_ci}
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_cistatic ssize_t
70562306a36Sopenharmony_cisdev_store_timeout (struct device *dev, struct device_attribute *attr,
70662306a36Sopenharmony_ci		    const char *buf, size_t count)
70762306a36Sopenharmony_ci{
70862306a36Sopenharmony_ci	struct scsi_device *sdev;
70962306a36Sopenharmony_ci	int timeout;
71062306a36Sopenharmony_ci	sdev = to_scsi_device(dev);
71162306a36Sopenharmony_ci	sscanf (buf, "%d\n", &timeout);
71262306a36Sopenharmony_ci	blk_queue_rq_timeout(sdev->request_queue, timeout * HZ);
71362306a36Sopenharmony_ci	return count;
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_cistatic DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_cistatic ssize_t
71862306a36Sopenharmony_cisdev_show_eh_timeout(struct device *dev, struct device_attribute *attr, char *buf)
71962306a36Sopenharmony_ci{
72062306a36Sopenharmony_ci	struct scsi_device *sdev;
72162306a36Sopenharmony_ci	sdev = to_scsi_device(dev);
72262306a36Sopenharmony_ci	return snprintf(buf, 20, "%u\n", sdev->eh_timeout / HZ);
72362306a36Sopenharmony_ci}
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_cistatic ssize_t
72662306a36Sopenharmony_cisdev_store_eh_timeout(struct device *dev, struct device_attribute *attr,
72762306a36Sopenharmony_ci		    const char *buf, size_t count)
72862306a36Sopenharmony_ci{
72962306a36Sopenharmony_ci	struct scsi_device *sdev;
73062306a36Sopenharmony_ci	unsigned int eh_timeout;
73162306a36Sopenharmony_ci	int err;
73262306a36Sopenharmony_ci
73362306a36Sopenharmony_ci	if (!capable(CAP_SYS_ADMIN))
73462306a36Sopenharmony_ci		return -EACCES;
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci	sdev = to_scsi_device(dev);
73762306a36Sopenharmony_ci	err = kstrtouint(buf, 10, &eh_timeout);
73862306a36Sopenharmony_ci	if (err)
73962306a36Sopenharmony_ci		return err;
74062306a36Sopenharmony_ci	sdev->eh_timeout = eh_timeout * HZ;
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	return count;
74362306a36Sopenharmony_ci}
74462306a36Sopenharmony_cistatic DEVICE_ATTR(eh_timeout, S_IRUGO | S_IWUSR, sdev_show_eh_timeout, sdev_store_eh_timeout);
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_cistatic ssize_t
74762306a36Sopenharmony_cistore_rescan_field (struct device *dev, struct device_attribute *attr,
74862306a36Sopenharmony_ci		    const char *buf, size_t count)
74962306a36Sopenharmony_ci{
75062306a36Sopenharmony_ci	scsi_rescan_device(to_scsi_device(dev));
75162306a36Sopenharmony_ci	return count;
75262306a36Sopenharmony_ci}
75362306a36Sopenharmony_cistatic DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_cistatic ssize_t
75662306a36Sopenharmony_cisdev_store_delete(struct device *dev, struct device_attribute *attr,
75762306a36Sopenharmony_ci		  const char *buf, size_t count)
75862306a36Sopenharmony_ci{
75962306a36Sopenharmony_ci	struct kernfs_node *kn;
76062306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	/*
76362306a36Sopenharmony_ci	 * We need to try to get module, avoiding the module been removed
76462306a36Sopenharmony_ci	 * during delete.
76562306a36Sopenharmony_ci	 */
76662306a36Sopenharmony_ci	if (scsi_device_get(sdev))
76762306a36Sopenharmony_ci		return -ENODEV;
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
77062306a36Sopenharmony_ci	WARN_ON_ONCE(!kn);
77162306a36Sopenharmony_ci	/*
77262306a36Sopenharmony_ci	 * Concurrent writes into the "delete" sysfs attribute may trigger
77362306a36Sopenharmony_ci	 * concurrent calls to device_remove_file() and scsi_remove_device().
77462306a36Sopenharmony_ci	 * device_remove_file() handles concurrent removal calls by
77562306a36Sopenharmony_ci	 * serializing these and by ignoring the second and later removal
77662306a36Sopenharmony_ci	 * attempts.  Concurrent calls of scsi_remove_device() are
77762306a36Sopenharmony_ci	 * serialized. The second and later calls of scsi_remove_device() are
77862306a36Sopenharmony_ci	 * ignored because the first call of that function changes the device
77962306a36Sopenharmony_ci	 * state into SDEV_DEL.
78062306a36Sopenharmony_ci	 */
78162306a36Sopenharmony_ci	device_remove_file(dev, attr);
78262306a36Sopenharmony_ci	scsi_remove_device(sdev);
78362306a36Sopenharmony_ci	if (kn)
78462306a36Sopenharmony_ci		sysfs_unbreak_active_protection(kn);
78562306a36Sopenharmony_ci	scsi_device_put(sdev);
78662306a36Sopenharmony_ci	return count;
78762306a36Sopenharmony_ci};
78862306a36Sopenharmony_cistatic DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_cistatic ssize_t
79162306a36Sopenharmony_cistore_state_field(struct device *dev, struct device_attribute *attr,
79262306a36Sopenharmony_ci		  const char *buf, size_t count)
79362306a36Sopenharmony_ci{
79462306a36Sopenharmony_ci	int i, ret;
79562306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
79662306a36Sopenharmony_ci	enum scsi_device_state state = 0;
79762306a36Sopenharmony_ci	bool rescan_dev = false;
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
80062306a36Sopenharmony_ci		const int len = strlen(sdev_states[i].name);
80162306a36Sopenharmony_ci		if (strncmp(sdev_states[i].name, buf, len) == 0 &&
80262306a36Sopenharmony_ci		   buf[len] == '\n') {
80362306a36Sopenharmony_ci			state = sdev_states[i].value;
80462306a36Sopenharmony_ci			break;
80562306a36Sopenharmony_ci		}
80662306a36Sopenharmony_ci	}
80762306a36Sopenharmony_ci	switch (state) {
80862306a36Sopenharmony_ci	case SDEV_RUNNING:
80962306a36Sopenharmony_ci	case SDEV_OFFLINE:
81062306a36Sopenharmony_ci		break;
81162306a36Sopenharmony_ci	default:
81262306a36Sopenharmony_ci		return -EINVAL;
81362306a36Sopenharmony_ci	}
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	mutex_lock(&sdev->state_mutex);
81662306a36Sopenharmony_ci	switch (sdev->sdev_state) {
81762306a36Sopenharmony_ci	case SDEV_RUNNING:
81862306a36Sopenharmony_ci	case SDEV_OFFLINE:
81962306a36Sopenharmony_ci		break;
82062306a36Sopenharmony_ci	default:
82162306a36Sopenharmony_ci		mutex_unlock(&sdev->state_mutex);
82262306a36Sopenharmony_ci		return -EINVAL;
82362306a36Sopenharmony_ci	}
82462306a36Sopenharmony_ci	if (sdev->sdev_state == SDEV_RUNNING && state == SDEV_RUNNING) {
82562306a36Sopenharmony_ci		ret = 0;
82662306a36Sopenharmony_ci	} else {
82762306a36Sopenharmony_ci		ret = scsi_device_set_state(sdev, state);
82862306a36Sopenharmony_ci		if (ret == 0 && state == SDEV_RUNNING)
82962306a36Sopenharmony_ci			rescan_dev = true;
83062306a36Sopenharmony_ci	}
83162306a36Sopenharmony_ci	mutex_unlock(&sdev->state_mutex);
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	if (rescan_dev) {
83462306a36Sopenharmony_ci		/*
83562306a36Sopenharmony_ci		 * If the device state changes to SDEV_RUNNING, we need to
83662306a36Sopenharmony_ci		 * run the queue to avoid I/O hang, and rescan the device
83762306a36Sopenharmony_ci		 * to revalidate it. Running the queue first is necessary
83862306a36Sopenharmony_ci		 * because another thread may be waiting inside
83962306a36Sopenharmony_ci		 * blk_mq_freeze_queue_wait() and because that call may be
84062306a36Sopenharmony_ci		 * waiting for pending I/O to finish.
84162306a36Sopenharmony_ci		 */
84262306a36Sopenharmony_ci		blk_mq_run_hw_queues(sdev->request_queue, true);
84362306a36Sopenharmony_ci		scsi_rescan_device(sdev);
84462306a36Sopenharmony_ci	}
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	return ret == 0 ? count : -EINVAL;
84762306a36Sopenharmony_ci}
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_cistatic ssize_t
85062306a36Sopenharmony_cishow_state_field(struct device *dev, struct device_attribute *attr, char *buf)
85162306a36Sopenharmony_ci{
85262306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
85362306a36Sopenharmony_ci	const char *name = scsi_device_state_name(sdev->sdev_state);
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	if (!name)
85662306a36Sopenharmony_ci		return -EINVAL;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	return snprintf(buf, 20, "%s\n", name);
85962306a36Sopenharmony_ci}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_cistatic DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_cistatic ssize_t
86462306a36Sopenharmony_cishow_queue_type_field(struct device *dev, struct device_attribute *attr,
86562306a36Sopenharmony_ci		      char *buf)
86662306a36Sopenharmony_ci{
86762306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
86862306a36Sopenharmony_ci	const char *name = "none";
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	if (sdev->simple_tags)
87162306a36Sopenharmony_ci		name = "simple";
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	return snprintf(buf, 20, "%s\n", name);
87462306a36Sopenharmony_ci}
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_cistatic ssize_t
87762306a36Sopenharmony_cistore_queue_type_field(struct device *dev, struct device_attribute *attr,
87862306a36Sopenharmony_ci		       const char *buf, size_t count)
87962306a36Sopenharmony_ci{
88062306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	if (!sdev->tagged_supported)
88362306a36Sopenharmony_ci		return -EINVAL;
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	sdev_printk(KERN_INFO, sdev,
88662306a36Sopenharmony_ci		    "ignoring write to deprecated queue_type attribute");
88762306a36Sopenharmony_ci	return count;
88862306a36Sopenharmony_ci}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_cistatic DEVICE_ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
89162306a36Sopenharmony_ci		   store_queue_type_field);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci#define sdev_vpd_pg_attr(_page)						\
89462306a36Sopenharmony_cistatic ssize_t							\
89562306a36Sopenharmony_cishow_vpd_##_page(struct file *filp, struct kobject *kobj,	\
89662306a36Sopenharmony_ci		 struct bin_attribute *bin_attr,			\
89762306a36Sopenharmony_ci		 char *buf, loff_t off, size_t count)			\
89862306a36Sopenharmony_ci{									\
89962306a36Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);				\
90062306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);			\
90162306a36Sopenharmony_ci	struct scsi_vpd *vpd_page;					\
90262306a36Sopenharmony_ci	int ret = -EINVAL;						\
90362306a36Sopenharmony_ci									\
90462306a36Sopenharmony_ci	rcu_read_lock();						\
90562306a36Sopenharmony_ci	vpd_page = rcu_dereference(sdev->vpd_##_page);			\
90662306a36Sopenharmony_ci	if (vpd_page)							\
90762306a36Sopenharmony_ci		ret = memory_read_from_buffer(buf, count, &off,		\
90862306a36Sopenharmony_ci				vpd_page->data, vpd_page->len);		\
90962306a36Sopenharmony_ci	rcu_read_unlock();						\
91062306a36Sopenharmony_ci	return ret;							\
91162306a36Sopenharmony_ci}									\
91262306a36Sopenharmony_cistatic struct bin_attribute dev_attr_vpd_##_page = {		\
91362306a36Sopenharmony_ci	.attr =	{.name = __stringify(vpd_##_page), .mode = S_IRUGO },	\
91462306a36Sopenharmony_ci	.size = 0,							\
91562306a36Sopenharmony_ci	.read = show_vpd_##_page,					\
91662306a36Sopenharmony_ci};
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_cisdev_vpd_pg_attr(pg83);
91962306a36Sopenharmony_cisdev_vpd_pg_attr(pg80);
92062306a36Sopenharmony_cisdev_vpd_pg_attr(pg89);
92162306a36Sopenharmony_cisdev_vpd_pg_attr(pgb0);
92262306a36Sopenharmony_cisdev_vpd_pg_attr(pgb1);
92362306a36Sopenharmony_cisdev_vpd_pg_attr(pgb2);
92462306a36Sopenharmony_cisdev_vpd_pg_attr(pg0);
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_cistatic ssize_t show_inquiry(struct file *filep, struct kobject *kobj,
92762306a36Sopenharmony_ci			    struct bin_attribute *bin_attr,
92862306a36Sopenharmony_ci			    char *buf, loff_t off, size_t count)
92962306a36Sopenharmony_ci{
93062306a36Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
93162306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	if (!sdev->inquiry)
93462306a36Sopenharmony_ci		return -EINVAL;
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	return memory_read_from_buffer(buf, count, &off, sdev->inquiry,
93762306a36Sopenharmony_ci				       sdev->inquiry_len);
93862306a36Sopenharmony_ci}
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_cistatic struct bin_attribute dev_attr_inquiry = {
94162306a36Sopenharmony_ci	.attr = {
94262306a36Sopenharmony_ci		.name = "inquiry",
94362306a36Sopenharmony_ci		.mode = S_IRUGO,
94462306a36Sopenharmony_ci	},
94562306a36Sopenharmony_ci	.size = 0,
94662306a36Sopenharmony_ci	.read = show_inquiry,
94762306a36Sopenharmony_ci};
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_cistatic ssize_t
95062306a36Sopenharmony_cishow_iostat_counterbits(struct device *dev, struct device_attribute *attr,
95162306a36Sopenharmony_ci			char *buf)
95262306a36Sopenharmony_ci{
95362306a36Sopenharmony_ci	return snprintf(buf, 20, "%d\n", (int)sizeof(atomic_t) * 8);
95462306a36Sopenharmony_ci}
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_cistatic DEVICE_ATTR(iocounterbits, S_IRUGO, show_iostat_counterbits, NULL);
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci#define show_sdev_iostat(field)						\
95962306a36Sopenharmony_cistatic ssize_t								\
96062306a36Sopenharmony_cishow_iostat_##field(struct device *dev, struct device_attribute *attr,	\
96162306a36Sopenharmony_ci		    char *buf)						\
96262306a36Sopenharmony_ci{									\
96362306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);			\
96462306a36Sopenharmony_ci	unsigned long long count = atomic_read(&sdev->field);		\
96562306a36Sopenharmony_ci	return snprintf(buf, 20, "0x%llx\n", count);			\
96662306a36Sopenharmony_ci}									\
96762306a36Sopenharmony_cistatic DEVICE_ATTR(field, S_IRUGO, show_iostat_##field, NULL)
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_cishow_sdev_iostat(iorequest_cnt);
97062306a36Sopenharmony_cishow_sdev_iostat(iodone_cnt);
97162306a36Sopenharmony_cishow_sdev_iostat(ioerr_cnt);
97262306a36Sopenharmony_cishow_sdev_iostat(iotmo_cnt);
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_cistatic ssize_t
97562306a36Sopenharmony_cisdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
97662306a36Sopenharmony_ci{
97762306a36Sopenharmony_ci	struct scsi_device *sdev;
97862306a36Sopenharmony_ci	sdev = to_scsi_device(dev);
97962306a36Sopenharmony_ci	return snprintf (buf, 20, SCSI_DEVICE_MODALIAS_FMT "\n", sdev->type);
98062306a36Sopenharmony_ci}
98162306a36Sopenharmony_cistatic DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci#define DECLARE_EVT_SHOW(name, Cap_name)				\
98462306a36Sopenharmony_cistatic ssize_t								\
98562306a36Sopenharmony_cisdev_show_evt_##name(struct device *dev, struct device_attribute *attr,	\
98662306a36Sopenharmony_ci		     char *buf)						\
98762306a36Sopenharmony_ci{									\
98862306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);			\
98962306a36Sopenharmony_ci	int val = test_bit(SDEV_EVT_##Cap_name, sdev->supported_events);\
99062306a36Sopenharmony_ci	return snprintf(buf, 20, "%d\n", val);				\
99162306a36Sopenharmony_ci}
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci#define DECLARE_EVT_STORE(name, Cap_name)				\
99462306a36Sopenharmony_cistatic ssize_t								\
99562306a36Sopenharmony_cisdev_store_evt_##name(struct device *dev, struct device_attribute *attr,\
99662306a36Sopenharmony_ci		      const char *buf, size_t count)			\
99762306a36Sopenharmony_ci{									\
99862306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);			\
99962306a36Sopenharmony_ci	int val = simple_strtoul(buf, NULL, 0);				\
100062306a36Sopenharmony_ci	if (val == 0)							\
100162306a36Sopenharmony_ci		clear_bit(SDEV_EVT_##Cap_name, sdev->supported_events);	\
100262306a36Sopenharmony_ci	else if (val == 1)						\
100362306a36Sopenharmony_ci		set_bit(SDEV_EVT_##Cap_name, sdev->supported_events);	\
100462306a36Sopenharmony_ci	else								\
100562306a36Sopenharmony_ci		return -EINVAL;						\
100662306a36Sopenharmony_ci	return count;							\
100762306a36Sopenharmony_ci}
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci#define DECLARE_EVT(name, Cap_name)					\
101062306a36Sopenharmony_ci	DECLARE_EVT_SHOW(name, Cap_name)				\
101162306a36Sopenharmony_ci	DECLARE_EVT_STORE(name, Cap_name)				\
101262306a36Sopenharmony_ci	static DEVICE_ATTR(evt_##name, S_IRUGO, sdev_show_evt_##name,	\
101362306a36Sopenharmony_ci			   sdev_store_evt_##name);
101462306a36Sopenharmony_ci#define REF_EVT(name) &dev_attr_evt_##name.attr
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ciDECLARE_EVT(media_change, MEDIA_CHANGE)
101762306a36Sopenharmony_ciDECLARE_EVT(inquiry_change_reported, INQUIRY_CHANGE_REPORTED)
101862306a36Sopenharmony_ciDECLARE_EVT(capacity_change_reported, CAPACITY_CHANGE_REPORTED)
101962306a36Sopenharmony_ciDECLARE_EVT(soft_threshold_reached, SOFT_THRESHOLD_REACHED_REPORTED)
102062306a36Sopenharmony_ciDECLARE_EVT(mode_parameter_change_reported, MODE_PARAMETER_CHANGE_REPORTED)
102162306a36Sopenharmony_ciDECLARE_EVT(lun_change_reported, LUN_CHANGE_REPORTED)
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_cistatic ssize_t
102462306a36Sopenharmony_cisdev_store_queue_depth(struct device *dev, struct device_attribute *attr,
102562306a36Sopenharmony_ci		       const char *buf, size_t count)
102662306a36Sopenharmony_ci{
102762306a36Sopenharmony_ci	int depth, retval;
102862306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
102962306a36Sopenharmony_ci	const struct scsi_host_template *sht = sdev->host->hostt;
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci	if (!sht->change_queue_depth)
103262306a36Sopenharmony_ci		return -EINVAL;
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	depth = simple_strtoul(buf, NULL, 0);
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	if (depth < 1 || depth > sdev->host->can_queue)
103762306a36Sopenharmony_ci		return -EINVAL;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	retval = sht->change_queue_depth(sdev, depth);
104062306a36Sopenharmony_ci	if (retval < 0)
104162306a36Sopenharmony_ci		return retval;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	sdev->max_queue_depth = sdev->queue_depth;
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	return count;
104662306a36Sopenharmony_ci}
104762306a36Sopenharmony_cisdev_show_function(queue_depth, "%d\n");
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_cistatic DEVICE_ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
105062306a36Sopenharmony_ci		   sdev_store_queue_depth);
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_cistatic ssize_t
105362306a36Sopenharmony_cisdev_show_wwid(struct device *dev, struct device_attribute *attr,
105462306a36Sopenharmony_ci		    char *buf)
105562306a36Sopenharmony_ci{
105662306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
105762306a36Sopenharmony_ci	ssize_t count;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	count = scsi_vpd_lun_id(sdev, buf, PAGE_SIZE);
106062306a36Sopenharmony_ci	if (count > 0) {
106162306a36Sopenharmony_ci		buf[count] = '\n';
106262306a36Sopenharmony_ci		count++;
106362306a36Sopenharmony_ci	}
106462306a36Sopenharmony_ci	return count;
106562306a36Sopenharmony_ci}
106662306a36Sopenharmony_cistatic DEVICE_ATTR(wwid, S_IRUGO, sdev_show_wwid, NULL);
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci#define BLIST_FLAG_NAME(name)					\
106962306a36Sopenharmony_ci	[const_ilog2((__force __u64)BLIST_##name)] = #name
107062306a36Sopenharmony_cistatic const char *const sdev_bflags_name[] = {
107162306a36Sopenharmony_ci#include "scsi_devinfo_tbl.c"
107262306a36Sopenharmony_ci};
107362306a36Sopenharmony_ci#undef BLIST_FLAG_NAME
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_cistatic ssize_t
107662306a36Sopenharmony_cisdev_show_blacklist(struct device *dev, struct device_attribute *attr,
107762306a36Sopenharmony_ci		    char *buf)
107862306a36Sopenharmony_ci{
107962306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
108062306a36Sopenharmony_ci	int i;
108162306a36Sopenharmony_ci	ssize_t len = 0;
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	for (i = 0; i < sizeof(sdev->sdev_bflags) * BITS_PER_BYTE; i++) {
108462306a36Sopenharmony_ci		const char *name = NULL;
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci		if (!(sdev->sdev_bflags & (__force blist_flags_t)BIT(i)))
108762306a36Sopenharmony_ci			continue;
108862306a36Sopenharmony_ci		if (i < ARRAY_SIZE(sdev_bflags_name) && sdev_bflags_name[i])
108962306a36Sopenharmony_ci			name = sdev_bflags_name[i];
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci		if (name)
109262306a36Sopenharmony_ci			len += scnprintf(buf + len, PAGE_SIZE - len,
109362306a36Sopenharmony_ci					 "%s%s", len ? " " : "", name);
109462306a36Sopenharmony_ci		else
109562306a36Sopenharmony_ci			len += scnprintf(buf + len, PAGE_SIZE - len,
109662306a36Sopenharmony_ci					 "%sINVALID_BIT(%d)", len ? " " : "", i);
109762306a36Sopenharmony_ci	}
109862306a36Sopenharmony_ci	if (len)
109962306a36Sopenharmony_ci		len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
110062306a36Sopenharmony_ci	return len;
110162306a36Sopenharmony_ci}
110262306a36Sopenharmony_cistatic DEVICE_ATTR(blacklist, S_IRUGO, sdev_show_blacklist, NULL);
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci#ifdef CONFIG_SCSI_DH
110562306a36Sopenharmony_cistatic ssize_t
110662306a36Sopenharmony_cisdev_show_dh_state(struct device *dev, struct device_attribute *attr,
110762306a36Sopenharmony_ci		   char *buf)
110862306a36Sopenharmony_ci{
110962306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	if (!sdev->handler)
111262306a36Sopenharmony_ci		return snprintf(buf, 20, "detached\n");
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	return snprintf(buf, 20, "%s\n", sdev->handler->name);
111562306a36Sopenharmony_ci}
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_cistatic ssize_t
111862306a36Sopenharmony_cisdev_store_dh_state(struct device *dev, struct device_attribute *attr,
111962306a36Sopenharmony_ci		    const char *buf, size_t count)
112062306a36Sopenharmony_ci{
112162306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
112262306a36Sopenharmony_ci	int err = -EINVAL;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	if (sdev->sdev_state == SDEV_CANCEL ||
112562306a36Sopenharmony_ci	    sdev->sdev_state == SDEV_DEL)
112662306a36Sopenharmony_ci		return -ENODEV;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	if (!sdev->handler) {
112962306a36Sopenharmony_ci		/*
113062306a36Sopenharmony_ci		 * Attach to a device handler
113162306a36Sopenharmony_ci		 */
113262306a36Sopenharmony_ci		err = scsi_dh_attach(sdev->request_queue, buf);
113362306a36Sopenharmony_ci	} else if (!strncmp(buf, "activate", 8)) {
113462306a36Sopenharmony_ci		/*
113562306a36Sopenharmony_ci		 * Activate a device handler
113662306a36Sopenharmony_ci		 */
113762306a36Sopenharmony_ci		if (sdev->handler->activate)
113862306a36Sopenharmony_ci			err = sdev->handler->activate(sdev, NULL, NULL);
113962306a36Sopenharmony_ci		else
114062306a36Sopenharmony_ci			err = 0;
114162306a36Sopenharmony_ci	} else if (!strncmp(buf, "detach", 6)) {
114262306a36Sopenharmony_ci		/*
114362306a36Sopenharmony_ci		 * Detach from a device handler
114462306a36Sopenharmony_ci		 */
114562306a36Sopenharmony_ci		sdev_printk(KERN_WARNING, sdev,
114662306a36Sopenharmony_ci			    "can't detach handler %s.\n",
114762306a36Sopenharmony_ci			    sdev->handler->name);
114862306a36Sopenharmony_ci		err = -EINVAL;
114962306a36Sopenharmony_ci	}
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	return err < 0 ? err : count;
115262306a36Sopenharmony_ci}
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_cistatic DEVICE_ATTR(dh_state, S_IRUGO | S_IWUSR, sdev_show_dh_state,
115562306a36Sopenharmony_ci		   sdev_store_dh_state);
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_cistatic ssize_t
115862306a36Sopenharmony_cisdev_show_access_state(struct device *dev,
115962306a36Sopenharmony_ci		       struct device_attribute *attr,
116062306a36Sopenharmony_ci		       char *buf)
116162306a36Sopenharmony_ci{
116262306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
116362306a36Sopenharmony_ci	unsigned char access_state;
116462306a36Sopenharmony_ci	const char *access_state_name;
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	if (!sdev->handler)
116762306a36Sopenharmony_ci		return -EINVAL;
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci	access_state = (sdev->access_state & SCSI_ACCESS_STATE_MASK);
117062306a36Sopenharmony_ci	access_state_name = scsi_access_state_name(access_state);
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci	return sprintf(buf, "%s\n",
117362306a36Sopenharmony_ci		       access_state_name ? access_state_name : "unknown");
117462306a36Sopenharmony_ci}
117562306a36Sopenharmony_cistatic DEVICE_ATTR(access_state, S_IRUGO, sdev_show_access_state, NULL);
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_cistatic ssize_t
117862306a36Sopenharmony_cisdev_show_preferred_path(struct device *dev,
117962306a36Sopenharmony_ci			 struct device_attribute *attr,
118062306a36Sopenharmony_ci			 char *buf)
118162306a36Sopenharmony_ci{
118262306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci	if (!sdev->handler)
118562306a36Sopenharmony_ci		return -EINVAL;
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci	if (sdev->access_state & SCSI_ACCESS_STATE_PREFERRED)
118862306a36Sopenharmony_ci		return sprintf(buf, "1\n");
118962306a36Sopenharmony_ci	else
119062306a36Sopenharmony_ci		return sprintf(buf, "0\n");
119162306a36Sopenharmony_ci}
119262306a36Sopenharmony_cistatic DEVICE_ATTR(preferred_path, S_IRUGO, sdev_show_preferred_path, NULL);
119362306a36Sopenharmony_ci#endif
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_cistatic ssize_t
119662306a36Sopenharmony_cisdev_show_queue_ramp_up_period(struct device *dev,
119762306a36Sopenharmony_ci			       struct device_attribute *attr,
119862306a36Sopenharmony_ci			       char *buf)
119962306a36Sopenharmony_ci{
120062306a36Sopenharmony_ci	struct scsi_device *sdev;
120162306a36Sopenharmony_ci	sdev = to_scsi_device(dev);
120262306a36Sopenharmony_ci	return snprintf(buf, 20, "%u\n",
120362306a36Sopenharmony_ci			jiffies_to_msecs(sdev->queue_ramp_up_period));
120462306a36Sopenharmony_ci}
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_cistatic ssize_t
120762306a36Sopenharmony_cisdev_store_queue_ramp_up_period(struct device *dev,
120862306a36Sopenharmony_ci				struct device_attribute *attr,
120962306a36Sopenharmony_ci				const char *buf, size_t count)
121062306a36Sopenharmony_ci{
121162306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
121262306a36Sopenharmony_ci	unsigned int period;
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	if (kstrtouint(buf, 10, &period))
121562306a36Sopenharmony_ci		return -EINVAL;
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	sdev->queue_ramp_up_period = msecs_to_jiffies(period);
121862306a36Sopenharmony_ci	return count;
121962306a36Sopenharmony_ci}
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_cistatic DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR,
122262306a36Sopenharmony_ci		   sdev_show_queue_ramp_up_period,
122362306a36Sopenharmony_ci		   sdev_store_queue_ramp_up_period);
122462306a36Sopenharmony_ci
122562306a36Sopenharmony_cistatic ssize_t sdev_show_cdl_enable(struct device *dev,
122662306a36Sopenharmony_ci				    struct device_attribute *attr, char *buf)
122762306a36Sopenharmony_ci{
122862306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	return sysfs_emit(buf, "%d\n", (int)sdev->cdl_enable);
123162306a36Sopenharmony_ci}
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_cistatic ssize_t sdev_store_cdl_enable(struct device *dev,
123462306a36Sopenharmony_ci				     struct device_attribute *attr,
123562306a36Sopenharmony_ci				     const char *buf, size_t count)
123662306a36Sopenharmony_ci{
123762306a36Sopenharmony_ci	int ret;
123862306a36Sopenharmony_ci	bool v;
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	if (kstrtobool(buf, &v))
124162306a36Sopenharmony_ci		return -EINVAL;
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_ci	ret = scsi_cdl_enable(to_scsi_device(dev), v);
124462306a36Sopenharmony_ci	if (ret)
124562306a36Sopenharmony_ci		return ret;
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	return count;
124862306a36Sopenharmony_ci}
124962306a36Sopenharmony_cistatic DEVICE_ATTR(cdl_enable, S_IRUGO | S_IWUSR,
125062306a36Sopenharmony_ci		   sdev_show_cdl_enable, sdev_store_cdl_enable);
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_cistatic umode_t scsi_sdev_attr_is_visible(struct kobject *kobj,
125362306a36Sopenharmony_ci					 struct attribute *attr, int i)
125462306a36Sopenharmony_ci{
125562306a36Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
125662306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	if (attr == &dev_attr_queue_depth.attr &&
126062306a36Sopenharmony_ci	    !sdev->host->hostt->change_queue_depth)
126162306a36Sopenharmony_ci		return S_IRUGO;
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci	if (attr == &dev_attr_queue_ramp_up_period.attr &&
126462306a36Sopenharmony_ci	    !sdev->host->hostt->change_queue_depth)
126562306a36Sopenharmony_ci		return 0;
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci	return attr->mode;
126862306a36Sopenharmony_ci}
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_cistatic umode_t scsi_sdev_bin_attr_is_visible(struct kobject *kobj,
127162306a36Sopenharmony_ci					     struct bin_attribute *attr, int i)
127262306a36Sopenharmony_ci{
127362306a36Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
127462306a36Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci	if (attr == &dev_attr_vpd_pg0 && !sdev->vpd_pg0)
127862306a36Sopenharmony_ci		return 0;
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_ci	if (attr == &dev_attr_vpd_pg80 && !sdev->vpd_pg80)
128162306a36Sopenharmony_ci		return 0;
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	if (attr == &dev_attr_vpd_pg83 && !sdev->vpd_pg83)
128462306a36Sopenharmony_ci		return 0;
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	if (attr == &dev_attr_vpd_pg89 && !sdev->vpd_pg89)
128762306a36Sopenharmony_ci		return 0;
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	if (attr == &dev_attr_vpd_pgb0 && !sdev->vpd_pgb0)
129062306a36Sopenharmony_ci		return 0;
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	if (attr == &dev_attr_vpd_pgb1 && !sdev->vpd_pgb1)
129362306a36Sopenharmony_ci		return 0;
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci	if (attr == &dev_attr_vpd_pgb2 && !sdev->vpd_pgb2)
129662306a36Sopenharmony_ci		return 0;
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	return S_IRUGO;
129962306a36Sopenharmony_ci}
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci/* Default template for device attributes.  May NOT be modified */
130262306a36Sopenharmony_cistatic struct attribute *scsi_sdev_attrs[] = {
130362306a36Sopenharmony_ci	&dev_attr_device_blocked.attr,
130462306a36Sopenharmony_ci	&dev_attr_type.attr,
130562306a36Sopenharmony_ci	&dev_attr_scsi_level.attr,
130662306a36Sopenharmony_ci	&dev_attr_device_busy.attr,
130762306a36Sopenharmony_ci	&dev_attr_vendor.attr,
130862306a36Sopenharmony_ci	&dev_attr_model.attr,
130962306a36Sopenharmony_ci	&dev_attr_rev.attr,
131062306a36Sopenharmony_ci	&dev_attr_rescan.attr,
131162306a36Sopenharmony_ci	&dev_attr_delete.attr,
131262306a36Sopenharmony_ci	&dev_attr_state.attr,
131362306a36Sopenharmony_ci	&dev_attr_timeout.attr,
131462306a36Sopenharmony_ci	&dev_attr_eh_timeout.attr,
131562306a36Sopenharmony_ci	&dev_attr_iocounterbits.attr,
131662306a36Sopenharmony_ci	&dev_attr_iorequest_cnt.attr,
131762306a36Sopenharmony_ci	&dev_attr_iodone_cnt.attr,
131862306a36Sopenharmony_ci	&dev_attr_ioerr_cnt.attr,
131962306a36Sopenharmony_ci	&dev_attr_iotmo_cnt.attr,
132062306a36Sopenharmony_ci	&dev_attr_modalias.attr,
132162306a36Sopenharmony_ci	&dev_attr_queue_depth.attr,
132262306a36Sopenharmony_ci	&dev_attr_queue_type.attr,
132362306a36Sopenharmony_ci	&dev_attr_wwid.attr,
132462306a36Sopenharmony_ci	&dev_attr_blacklist.attr,
132562306a36Sopenharmony_ci#ifdef CONFIG_SCSI_DH
132662306a36Sopenharmony_ci	&dev_attr_dh_state.attr,
132762306a36Sopenharmony_ci	&dev_attr_access_state.attr,
132862306a36Sopenharmony_ci	&dev_attr_preferred_path.attr,
132962306a36Sopenharmony_ci#endif
133062306a36Sopenharmony_ci	&dev_attr_queue_ramp_up_period.attr,
133162306a36Sopenharmony_ci	&dev_attr_cdl_supported.attr,
133262306a36Sopenharmony_ci	&dev_attr_cdl_enable.attr,
133362306a36Sopenharmony_ci	REF_EVT(media_change),
133462306a36Sopenharmony_ci	REF_EVT(inquiry_change_reported),
133562306a36Sopenharmony_ci	REF_EVT(capacity_change_reported),
133662306a36Sopenharmony_ci	REF_EVT(soft_threshold_reached),
133762306a36Sopenharmony_ci	REF_EVT(mode_parameter_change_reported),
133862306a36Sopenharmony_ci	REF_EVT(lun_change_reported),
133962306a36Sopenharmony_ci	NULL
134062306a36Sopenharmony_ci};
134162306a36Sopenharmony_ci
134262306a36Sopenharmony_cistatic struct bin_attribute *scsi_sdev_bin_attrs[] = {
134362306a36Sopenharmony_ci	&dev_attr_vpd_pg0,
134462306a36Sopenharmony_ci	&dev_attr_vpd_pg83,
134562306a36Sopenharmony_ci	&dev_attr_vpd_pg80,
134662306a36Sopenharmony_ci	&dev_attr_vpd_pg89,
134762306a36Sopenharmony_ci	&dev_attr_vpd_pgb0,
134862306a36Sopenharmony_ci	&dev_attr_vpd_pgb1,
134962306a36Sopenharmony_ci	&dev_attr_vpd_pgb2,
135062306a36Sopenharmony_ci	&dev_attr_inquiry,
135162306a36Sopenharmony_ci	NULL
135262306a36Sopenharmony_ci};
135362306a36Sopenharmony_cistatic struct attribute_group scsi_sdev_attr_group = {
135462306a36Sopenharmony_ci	.attrs =	scsi_sdev_attrs,
135562306a36Sopenharmony_ci	.bin_attrs =	scsi_sdev_bin_attrs,
135662306a36Sopenharmony_ci	.is_visible =	scsi_sdev_attr_is_visible,
135762306a36Sopenharmony_ci	.is_bin_visible = scsi_sdev_bin_attr_is_visible,
135862306a36Sopenharmony_ci};
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_cistatic const struct attribute_group *scsi_sdev_attr_groups[] = {
136162306a36Sopenharmony_ci	&scsi_sdev_attr_group,
136262306a36Sopenharmony_ci	NULL
136362306a36Sopenharmony_ci};
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_cistatic int scsi_target_add(struct scsi_target *starget)
136662306a36Sopenharmony_ci{
136762306a36Sopenharmony_ci	int error;
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci	if (starget->state != STARGET_CREATED)
137062306a36Sopenharmony_ci		return 0;
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	error = device_add(&starget->dev);
137362306a36Sopenharmony_ci	if (error) {
137462306a36Sopenharmony_ci		dev_err(&starget->dev, "target device_add failed, error %d\n", error);
137562306a36Sopenharmony_ci		return error;
137662306a36Sopenharmony_ci	}
137762306a36Sopenharmony_ci	transport_add_device(&starget->dev);
137862306a36Sopenharmony_ci	starget->state = STARGET_RUNNING;
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	pm_runtime_set_active(&starget->dev);
138162306a36Sopenharmony_ci	pm_runtime_enable(&starget->dev);
138262306a36Sopenharmony_ci	device_enable_async_suspend(&starget->dev);
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_ci	return 0;
138562306a36Sopenharmony_ci}
138662306a36Sopenharmony_ci
138762306a36Sopenharmony_ci/**
138862306a36Sopenharmony_ci * scsi_sysfs_add_sdev - add scsi device to sysfs
138962306a36Sopenharmony_ci * @sdev:	scsi_device to add
139062306a36Sopenharmony_ci *
139162306a36Sopenharmony_ci * Return value:
139262306a36Sopenharmony_ci * 	0 on Success / non-zero on Failure
139362306a36Sopenharmony_ci **/
139462306a36Sopenharmony_ciint scsi_sysfs_add_sdev(struct scsi_device *sdev)
139562306a36Sopenharmony_ci{
139662306a36Sopenharmony_ci	int error;
139762306a36Sopenharmony_ci	struct scsi_target *starget = sdev->sdev_target;
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_ci	error = scsi_target_add(starget);
140062306a36Sopenharmony_ci	if (error)
140162306a36Sopenharmony_ci		return error;
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci	transport_configure_device(&starget->dev);
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	device_enable_async_suspend(&sdev->sdev_gendev);
140662306a36Sopenharmony_ci	scsi_autopm_get_target(starget);
140762306a36Sopenharmony_ci	pm_runtime_set_active(&sdev->sdev_gendev);
140862306a36Sopenharmony_ci	if (!sdev->rpm_autosuspend)
140962306a36Sopenharmony_ci		pm_runtime_forbid(&sdev->sdev_gendev);
141062306a36Sopenharmony_ci	pm_runtime_enable(&sdev->sdev_gendev);
141162306a36Sopenharmony_ci	scsi_autopm_put_target(starget);
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci	scsi_autopm_get_device(sdev);
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	scsi_dh_add_device(sdev);
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	error = device_add(&sdev->sdev_gendev);
141862306a36Sopenharmony_ci	if (error) {
141962306a36Sopenharmony_ci		sdev_printk(KERN_INFO, sdev,
142062306a36Sopenharmony_ci				"failed to add device: %d\n", error);
142162306a36Sopenharmony_ci		return error;
142262306a36Sopenharmony_ci	}
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci	device_enable_async_suspend(&sdev->sdev_dev);
142562306a36Sopenharmony_ci	error = device_add(&sdev->sdev_dev);
142662306a36Sopenharmony_ci	if (error) {
142762306a36Sopenharmony_ci		sdev_printk(KERN_INFO, sdev,
142862306a36Sopenharmony_ci				"failed to add class device: %d\n", error);
142962306a36Sopenharmony_ci		device_del(&sdev->sdev_gendev);
143062306a36Sopenharmony_ci		return error;
143162306a36Sopenharmony_ci	}
143262306a36Sopenharmony_ci	transport_add_device(&sdev->sdev_gendev);
143362306a36Sopenharmony_ci	sdev->is_visible = 1;
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_BLK_DEV_BSG)) {
143662306a36Sopenharmony_ci		sdev->bsg_dev = scsi_bsg_register_queue(sdev);
143762306a36Sopenharmony_ci		if (IS_ERR(sdev->bsg_dev)) {
143862306a36Sopenharmony_ci			error = PTR_ERR(sdev->bsg_dev);
143962306a36Sopenharmony_ci			sdev_printk(KERN_INFO, sdev,
144062306a36Sopenharmony_ci				    "Failed to register bsg queue, errno=%d\n",
144162306a36Sopenharmony_ci				    error);
144262306a36Sopenharmony_ci			sdev->bsg_dev = NULL;
144362306a36Sopenharmony_ci		}
144462306a36Sopenharmony_ci	}
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	scsi_autopm_put_device(sdev);
144762306a36Sopenharmony_ci	return error;
144862306a36Sopenharmony_ci}
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_civoid __scsi_remove_device(struct scsi_device *sdev)
145162306a36Sopenharmony_ci{
145262306a36Sopenharmony_ci	struct device *dev = &sdev->sdev_gendev;
145362306a36Sopenharmony_ci	int res;
145462306a36Sopenharmony_ci
145562306a36Sopenharmony_ci	/*
145662306a36Sopenharmony_ci	 * This cleanup path is not reentrant and while it is impossible
145762306a36Sopenharmony_ci	 * to get a new reference with scsi_device_get() someone can still
145862306a36Sopenharmony_ci	 * hold a previously acquired one.
145962306a36Sopenharmony_ci	 */
146062306a36Sopenharmony_ci	if (sdev->sdev_state == SDEV_DEL)
146162306a36Sopenharmony_ci		return;
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	if (sdev->is_visible) {
146462306a36Sopenharmony_ci		/*
146562306a36Sopenharmony_ci		 * If scsi_internal_target_block() is running concurrently,
146662306a36Sopenharmony_ci		 * wait until it has finished before changing the device state.
146762306a36Sopenharmony_ci		 */
146862306a36Sopenharmony_ci		mutex_lock(&sdev->state_mutex);
146962306a36Sopenharmony_ci		/*
147062306a36Sopenharmony_ci		 * If blocked, we go straight to DEL and restart the queue so
147162306a36Sopenharmony_ci		 * any commands issued during driver shutdown (like sync
147262306a36Sopenharmony_ci		 * cache) are errored immediately.
147362306a36Sopenharmony_ci		 */
147462306a36Sopenharmony_ci		res = scsi_device_set_state(sdev, SDEV_CANCEL);
147562306a36Sopenharmony_ci		if (res != 0) {
147662306a36Sopenharmony_ci			res = scsi_device_set_state(sdev, SDEV_DEL);
147762306a36Sopenharmony_ci			if (res == 0)
147862306a36Sopenharmony_ci				scsi_start_queue(sdev);
147962306a36Sopenharmony_ci		}
148062306a36Sopenharmony_ci		mutex_unlock(&sdev->state_mutex);
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci		if (res != 0)
148362306a36Sopenharmony_ci			return;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci		if (IS_ENABLED(CONFIG_BLK_DEV_BSG) && sdev->bsg_dev)
148662306a36Sopenharmony_ci			bsg_unregister_queue(sdev->bsg_dev);
148762306a36Sopenharmony_ci		device_unregister(&sdev->sdev_dev);
148862306a36Sopenharmony_ci		transport_remove_device(dev);
148962306a36Sopenharmony_ci		device_del(dev);
149062306a36Sopenharmony_ci	} else
149162306a36Sopenharmony_ci		put_device(&sdev->sdev_dev);
149262306a36Sopenharmony_ci
149362306a36Sopenharmony_ci	/*
149462306a36Sopenharmony_ci	 * Stop accepting new requests and wait until all queuecommand() and
149562306a36Sopenharmony_ci	 * scsi_run_queue() invocations have finished before tearing down the
149662306a36Sopenharmony_ci	 * device.
149762306a36Sopenharmony_ci	 */
149862306a36Sopenharmony_ci	mutex_lock(&sdev->state_mutex);
149962306a36Sopenharmony_ci	scsi_device_set_state(sdev, SDEV_DEL);
150062306a36Sopenharmony_ci	mutex_unlock(&sdev->state_mutex);
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	blk_mq_destroy_queue(sdev->request_queue);
150362306a36Sopenharmony_ci	kref_put(&sdev->host->tagset_refcnt, scsi_mq_free_tags);
150462306a36Sopenharmony_ci	cancel_work_sync(&sdev->requeue_work);
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_ci	if (sdev->host->hostt->slave_destroy)
150762306a36Sopenharmony_ci		sdev->host->hostt->slave_destroy(sdev);
150862306a36Sopenharmony_ci	transport_destroy_device(dev);
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ci	/*
151162306a36Sopenharmony_ci	 * Paired with the kref_get() in scsi_sysfs_initialize().  We have
151262306a36Sopenharmony_ci	 * removed sysfs visibility from the device, so make the target
151362306a36Sopenharmony_ci	 * invisible if this was the last device underneath it.
151462306a36Sopenharmony_ci	 */
151562306a36Sopenharmony_ci	scsi_target_reap(scsi_target(sdev));
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	put_device(dev);
151862306a36Sopenharmony_ci}
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci/**
152162306a36Sopenharmony_ci * scsi_remove_device - unregister a device from the scsi bus
152262306a36Sopenharmony_ci * @sdev:	scsi_device to unregister
152362306a36Sopenharmony_ci **/
152462306a36Sopenharmony_civoid scsi_remove_device(struct scsi_device *sdev)
152562306a36Sopenharmony_ci{
152662306a36Sopenharmony_ci	struct Scsi_Host *shost = sdev->host;
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci	mutex_lock(&shost->scan_mutex);
152962306a36Sopenharmony_ci	__scsi_remove_device(sdev);
153062306a36Sopenharmony_ci	mutex_unlock(&shost->scan_mutex);
153162306a36Sopenharmony_ci}
153262306a36Sopenharmony_ciEXPORT_SYMBOL(scsi_remove_device);
153362306a36Sopenharmony_ci
153462306a36Sopenharmony_cistatic void __scsi_remove_target(struct scsi_target *starget)
153562306a36Sopenharmony_ci{
153662306a36Sopenharmony_ci	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
153762306a36Sopenharmony_ci	unsigned long flags;
153862306a36Sopenharmony_ci	struct scsi_device *sdev;
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	spin_lock_irqsave(shost->host_lock, flags);
154162306a36Sopenharmony_ci restart:
154262306a36Sopenharmony_ci	list_for_each_entry(sdev, &shost->__devices, siblings) {
154362306a36Sopenharmony_ci		/*
154462306a36Sopenharmony_ci		 * We cannot call scsi_device_get() here, as
154562306a36Sopenharmony_ci		 * we might've been called from rmmod() causing
154662306a36Sopenharmony_ci		 * scsi_device_get() to fail the module_is_live()
154762306a36Sopenharmony_ci		 * check.
154862306a36Sopenharmony_ci		 */
154962306a36Sopenharmony_ci		if (sdev->channel != starget->channel ||
155062306a36Sopenharmony_ci		    sdev->id != starget->id)
155162306a36Sopenharmony_ci			continue;
155262306a36Sopenharmony_ci		if (sdev->sdev_state == SDEV_DEL ||
155362306a36Sopenharmony_ci		    sdev->sdev_state == SDEV_CANCEL ||
155462306a36Sopenharmony_ci		    !get_device(&sdev->sdev_gendev))
155562306a36Sopenharmony_ci			continue;
155662306a36Sopenharmony_ci		spin_unlock_irqrestore(shost->host_lock, flags);
155762306a36Sopenharmony_ci		scsi_remove_device(sdev);
155862306a36Sopenharmony_ci		put_device(&sdev->sdev_gendev);
155962306a36Sopenharmony_ci		spin_lock_irqsave(shost->host_lock, flags);
156062306a36Sopenharmony_ci		goto restart;
156162306a36Sopenharmony_ci	}
156262306a36Sopenharmony_ci	spin_unlock_irqrestore(shost->host_lock, flags);
156362306a36Sopenharmony_ci}
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci/**
156662306a36Sopenharmony_ci * scsi_remove_target - try to remove a target and all its devices
156762306a36Sopenharmony_ci * @dev: generic starget or parent of generic stargets to be removed
156862306a36Sopenharmony_ci *
156962306a36Sopenharmony_ci * Note: This is slightly racy.  It is possible that if the user
157062306a36Sopenharmony_ci * requests the addition of another device then the target won't be
157162306a36Sopenharmony_ci * removed.
157262306a36Sopenharmony_ci */
157362306a36Sopenharmony_civoid scsi_remove_target(struct device *dev)
157462306a36Sopenharmony_ci{
157562306a36Sopenharmony_ci	struct Scsi_Host *shost = dev_to_shost(dev->parent);
157662306a36Sopenharmony_ci	struct scsi_target *starget;
157762306a36Sopenharmony_ci	unsigned long flags;
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_cirestart:
158062306a36Sopenharmony_ci	spin_lock_irqsave(shost->host_lock, flags);
158162306a36Sopenharmony_ci	list_for_each_entry(starget, &shost->__targets, siblings) {
158262306a36Sopenharmony_ci		if (starget->state == STARGET_DEL ||
158362306a36Sopenharmony_ci		    starget->state == STARGET_REMOVE ||
158462306a36Sopenharmony_ci		    starget->state == STARGET_CREATED_REMOVE)
158562306a36Sopenharmony_ci			continue;
158662306a36Sopenharmony_ci		if (starget->dev.parent == dev || &starget->dev == dev) {
158762306a36Sopenharmony_ci			kref_get(&starget->reap_ref);
158862306a36Sopenharmony_ci			if (starget->state == STARGET_CREATED)
158962306a36Sopenharmony_ci				starget->state = STARGET_CREATED_REMOVE;
159062306a36Sopenharmony_ci			else
159162306a36Sopenharmony_ci				starget->state = STARGET_REMOVE;
159262306a36Sopenharmony_ci			spin_unlock_irqrestore(shost->host_lock, flags);
159362306a36Sopenharmony_ci			__scsi_remove_target(starget);
159462306a36Sopenharmony_ci			scsi_target_reap(starget);
159562306a36Sopenharmony_ci			goto restart;
159662306a36Sopenharmony_ci		}
159762306a36Sopenharmony_ci	}
159862306a36Sopenharmony_ci	spin_unlock_irqrestore(shost->host_lock, flags);
159962306a36Sopenharmony_ci}
160062306a36Sopenharmony_ciEXPORT_SYMBOL(scsi_remove_target);
160162306a36Sopenharmony_ci
160262306a36Sopenharmony_ciint scsi_register_driver(struct device_driver *drv)
160362306a36Sopenharmony_ci{
160462306a36Sopenharmony_ci	drv->bus = &scsi_bus_type;
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	return driver_register(drv);
160762306a36Sopenharmony_ci}
160862306a36Sopenharmony_ciEXPORT_SYMBOL(scsi_register_driver);
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ciint scsi_register_interface(struct class_interface *intf)
161162306a36Sopenharmony_ci{
161262306a36Sopenharmony_ci	intf->class = &sdev_class;
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_ci	return class_interface_register(intf);
161562306a36Sopenharmony_ci}
161662306a36Sopenharmony_ciEXPORT_SYMBOL(scsi_register_interface);
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci/**
161962306a36Sopenharmony_ci * scsi_sysfs_add_host - add scsi host to subsystem
162062306a36Sopenharmony_ci * @shost:     scsi host struct to add to subsystem
162162306a36Sopenharmony_ci **/
162262306a36Sopenharmony_ciint scsi_sysfs_add_host(struct Scsi_Host *shost)
162362306a36Sopenharmony_ci{
162462306a36Sopenharmony_ci	transport_register_device(&shost->shost_gendev);
162562306a36Sopenharmony_ci	transport_configure_device(&shost->shost_gendev);
162662306a36Sopenharmony_ci	return 0;
162762306a36Sopenharmony_ci}
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_cistatic struct device_type scsi_dev_type = {
163062306a36Sopenharmony_ci	.name =		"scsi_device",
163162306a36Sopenharmony_ci	.release =	scsi_device_dev_release,
163262306a36Sopenharmony_ci	.groups =	scsi_sdev_attr_groups,
163362306a36Sopenharmony_ci};
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_civoid scsi_sysfs_device_initialize(struct scsi_device *sdev)
163662306a36Sopenharmony_ci{
163762306a36Sopenharmony_ci	unsigned long flags;
163862306a36Sopenharmony_ci	struct Scsi_Host *shost = sdev->host;
163962306a36Sopenharmony_ci	const struct scsi_host_template *hostt = shost->hostt;
164062306a36Sopenharmony_ci	struct scsi_target  *starget = sdev->sdev_target;
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_ci	device_initialize(&sdev->sdev_gendev);
164362306a36Sopenharmony_ci	sdev->sdev_gendev.bus = &scsi_bus_type;
164462306a36Sopenharmony_ci	sdev->sdev_gendev.type = &scsi_dev_type;
164562306a36Sopenharmony_ci	scsi_enable_async_suspend(&sdev->sdev_gendev);
164662306a36Sopenharmony_ci	dev_set_name(&sdev->sdev_gendev, "%d:%d:%d:%llu",
164762306a36Sopenharmony_ci		     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
164862306a36Sopenharmony_ci	sdev->sdev_gendev.groups = hostt->sdev_groups;
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci	device_initialize(&sdev->sdev_dev);
165162306a36Sopenharmony_ci	sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev);
165262306a36Sopenharmony_ci	sdev->sdev_dev.class = &sdev_class;
165362306a36Sopenharmony_ci	dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%llu",
165462306a36Sopenharmony_ci		     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
165562306a36Sopenharmony_ci	/*
165662306a36Sopenharmony_ci	 * Get a default scsi_level from the target (derived from sibling
165762306a36Sopenharmony_ci	 * devices).  This is the best we can do for guessing how to set
165862306a36Sopenharmony_ci	 * sdev->lun_in_cdb for the initial INQUIRY command.  For LUN 0 the
165962306a36Sopenharmony_ci	 * setting doesn't matter, because all the bits are zero anyway.
166062306a36Sopenharmony_ci	 * But it does matter for higher LUNs.
166162306a36Sopenharmony_ci	 */
166262306a36Sopenharmony_ci	sdev->scsi_level = starget->scsi_level;
166362306a36Sopenharmony_ci	if (sdev->scsi_level <= SCSI_2 &&
166462306a36Sopenharmony_ci			sdev->scsi_level != SCSI_UNKNOWN &&
166562306a36Sopenharmony_ci			!shost->no_scsi2_lun_in_cdb)
166662306a36Sopenharmony_ci		sdev->lun_in_cdb = 1;
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci	transport_setup_device(&sdev->sdev_gendev);
166962306a36Sopenharmony_ci	spin_lock_irqsave(shost->host_lock, flags);
167062306a36Sopenharmony_ci	list_add_tail(&sdev->same_target_siblings, &starget->devices);
167162306a36Sopenharmony_ci	list_add_tail(&sdev->siblings, &shost->__devices);
167262306a36Sopenharmony_ci	spin_unlock_irqrestore(shost->host_lock, flags);
167362306a36Sopenharmony_ci	/*
167462306a36Sopenharmony_ci	 * device can now only be removed via __scsi_remove_device() so hold
167562306a36Sopenharmony_ci	 * the target.  Target will be held in CREATED state until something
167662306a36Sopenharmony_ci	 * beneath it becomes visible (in which case it moves to RUNNING)
167762306a36Sopenharmony_ci	 */
167862306a36Sopenharmony_ci	kref_get(&starget->reap_ref);
167962306a36Sopenharmony_ci}
168062306a36Sopenharmony_ci
168162306a36Sopenharmony_ciint scsi_is_sdev_device(const struct device *dev)
168262306a36Sopenharmony_ci{
168362306a36Sopenharmony_ci	return dev->type == &scsi_dev_type;
168462306a36Sopenharmony_ci}
168562306a36Sopenharmony_ciEXPORT_SYMBOL(scsi_is_sdev_device);
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_ci/* A blank transport template that is used in drivers that don't
168862306a36Sopenharmony_ci * yet implement Transport Attributes */
168962306a36Sopenharmony_cistruct scsi_transport_template blank_transport_template = { { { {NULL, }, }, }, };
1690