xref: /openbmc/linux/drivers/scsi/scsi_sysfs.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * scsi_sysfs.c
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  * SCSI sysfs interface routines.
5*1da177e4SLinus Torvalds  *
6*1da177e4SLinus Torvalds  * Created to pull SCSI mid layer sysfs routines into one file.
7*1da177e4SLinus Torvalds  */
8*1da177e4SLinus Torvalds 
9*1da177e4SLinus Torvalds #include <linux/config.h>
10*1da177e4SLinus Torvalds #include <linux/module.h>
11*1da177e4SLinus Torvalds #include <linux/init.h>
12*1da177e4SLinus Torvalds #include <linux/blkdev.h>
13*1da177e4SLinus Torvalds #include <linux/device.h>
14*1da177e4SLinus Torvalds 
15*1da177e4SLinus Torvalds #include <scsi/scsi.h>
16*1da177e4SLinus Torvalds #include <scsi/scsi_device.h>
17*1da177e4SLinus Torvalds #include <scsi/scsi_host.h>
18*1da177e4SLinus Torvalds #include <scsi/scsi_tcq.h>
19*1da177e4SLinus Torvalds #include <scsi/scsi_transport.h>
20*1da177e4SLinus Torvalds 
21*1da177e4SLinus Torvalds #include "scsi_priv.h"
22*1da177e4SLinus Torvalds #include "scsi_logging.h"
23*1da177e4SLinus Torvalds 
24*1da177e4SLinus Torvalds static struct {
25*1da177e4SLinus Torvalds 	enum scsi_device_state	value;
26*1da177e4SLinus Torvalds 	char			*name;
27*1da177e4SLinus Torvalds } sdev_states[] = {
28*1da177e4SLinus Torvalds 	{ SDEV_CREATED, "created" },
29*1da177e4SLinus Torvalds 	{ SDEV_RUNNING, "running" },
30*1da177e4SLinus Torvalds 	{ SDEV_CANCEL, "cancel" },
31*1da177e4SLinus Torvalds 	{ SDEV_DEL, "deleted" },
32*1da177e4SLinus Torvalds 	{ SDEV_QUIESCE, "quiesce" },
33*1da177e4SLinus Torvalds 	{ SDEV_OFFLINE,	"offline" },
34*1da177e4SLinus Torvalds 	{ SDEV_BLOCK,	"blocked" },
35*1da177e4SLinus Torvalds };
36*1da177e4SLinus Torvalds 
37*1da177e4SLinus Torvalds const char *scsi_device_state_name(enum scsi_device_state state)
38*1da177e4SLinus Torvalds {
39*1da177e4SLinus Torvalds 	int i;
40*1da177e4SLinus Torvalds 	char *name = NULL;
41*1da177e4SLinus Torvalds 
42*1da177e4SLinus Torvalds 	for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) {
43*1da177e4SLinus Torvalds 		if (sdev_states[i].value == state) {
44*1da177e4SLinus Torvalds 			name = sdev_states[i].name;
45*1da177e4SLinus Torvalds 			break;
46*1da177e4SLinus Torvalds 		}
47*1da177e4SLinus Torvalds 	}
48*1da177e4SLinus Torvalds 	return name;
49*1da177e4SLinus Torvalds }
50*1da177e4SLinus Torvalds 
51*1da177e4SLinus Torvalds static int check_set(unsigned int *val, char *src)
52*1da177e4SLinus Torvalds {
53*1da177e4SLinus Torvalds 	char *last;
54*1da177e4SLinus Torvalds 
55*1da177e4SLinus Torvalds 	if (strncmp(src, "-", 20) == 0) {
56*1da177e4SLinus Torvalds 		*val = SCAN_WILD_CARD;
57*1da177e4SLinus Torvalds 	} else {
58*1da177e4SLinus Torvalds 		/*
59*1da177e4SLinus Torvalds 		 * Doesn't check for int overflow
60*1da177e4SLinus Torvalds 		 */
61*1da177e4SLinus Torvalds 		*val = simple_strtoul(src, &last, 0);
62*1da177e4SLinus Torvalds 		if (*last != '\0')
63*1da177e4SLinus Torvalds 			return 1;
64*1da177e4SLinus Torvalds 	}
65*1da177e4SLinus Torvalds 	return 0;
66*1da177e4SLinus Torvalds }
67*1da177e4SLinus Torvalds 
68*1da177e4SLinus Torvalds static int scsi_scan(struct Scsi_Host *shost, const char *str)
69*1da177e4SLinus Torvalds {
70*1da177e4SLinus Torvalds 	char s1[15], s2[15], s3[15], junk;
71*1da177e4SLinus Torvalds 	unsigned int channel, id, lun;
72*1da177e4SLinus Torvalds 	int res;
73*1da177e4SLinus Torvalds 
74*1da177e4SLinus Torvalds 	res = sscanf(str, "%10s %10s %10s %c", s1, s2, s3, &junk);
75*1da177e4SLinus Torvalds 	if (res != 3)
76*1da177e4SLinus Torvalds 		return -EINVAL;
77*1da177e4SLinus Torvalds 	if (check_set(&channel, s1))
78*1da177e4SLinus Torvalds 		return -EINVAL;
79*1da177e4SLinus Torvalds 	if (check_set(&id, s2))
80*1da177e4SLinus Torvalds 		return -EINVAL;
81*1da177e4SLinus Torvalds 	if (check_set(&lun, s3))
82*1da177e4SLinus Torvalds 		return -EINVAL;
83*1da177e4SLinus Torvalds 	res = scsi_scan_host_selected(shost, channel, id, lun, 1);
84*1da177e4SLinus Torvalds 	return res;
85*1da177e4SLinus Torvalds }
86*1da177e4SLinus Torvalds 
87*1da177e4SLinus Torvalds /*
88*1da177e4SLinus Torvalds  * shost_show_function: macro to create an attr function that can be used to
89*1da177e4SLinus Torvalds  * show a non-bit field.
90*1da177e4SLinus Torvalds  */
91*1da177e4SLinus Torvalds #define shost_show_function(name, field, format_string)			\
92*1da177e4SLinus Torvalds static ssize_t								\
93*1da177e4SLinus Torvalds show_##name (struct class_device *class_dev, char *buf)			\
94*1da177e4SLinus Torvalds {									\
95*1da177e4SLinus Torvalds 	struct Scsi_Host *shost = class_to_shost(class_dev);		\
96*1da177e4SLinus Torvalds 	return snprintf (buf, 20, format_string, shost->field);		\
97*1da177e4SLinus Torvalds }
98*1da177e4SLinus Torvalds 
99*1da177e4SLinus Torvalds /*
100*1da177e4SLinus Torvalds  * shost_rd_attr: macro to create a function and attribute variable for a
101*1da177e4SLinus Torvalds  * read only field.
102*1da177e4SLinus Torvalds  */
103*1da177e4SLinus Torvalds #define shost_rd_attr2(name, field, format_string)			\
104*1da177e4SLinus Torvalds 	shost_show_function(name, field, format_string)			\
105*1da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
106*1da177e4SLinus Torvalds 
107*1da177e4SLinus Torvalds #define shost_rd_attr(field, format_string) \
108*1da177e4SLinus Torvalds shost_rd_attr2(field, field, format_string)
109*1da177e4SLinus Torvalds 
110*1da177e4SLinus Torvalds /*
111*1da177e4SLinus Torvalds  * Create the actual show/store functions and data structures.
112*1da177e4SLinus Torvalds  */
113*1da177e4SLinus Torvalds 
114*1da177e4SLinus Torvalds static ssize_t store_scan(struct class_device *class_dev, const char *buf,
115*1da177e4SLinus Torvalds 			  size_t count)
116*1da177e4SLinus Torvalds {
117*1da177e4SLinus Torvalds 	struct Scsi_Host *shost = class_to_shost(class_dev);
118*1da177e4SLinus Torvalds 	int res;
119*1da177e4SLinus Torvalds 
120*1da177e4SLinus Torvalds 	res = scsi_scan(shost, buf);
121*1da177e4SLinus Torvalds 	if (res == 0)
122*1da177e4SLinus Torvalds 		res = count;
123*1da177e4SLinus Torvalds 	return res;
124*1da177e4SLinus Torvalds };
125*1da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
126*1da177e4SLinus Torvalds 
127*1da177e4SLinus Torvalds shost_rd_attr(unique_id, "%u\n");
128*1da177e4SLinus Torvalds shost_rd_attr(host_busy, "%hu\n");
129*1da177e4SLinus Torvalds shost_rd_attr(cmd_per_lun, "%hd\n");
130*1da177e4SLinus Torvalds shost_rd_attr(sg_tablesize, "%hu\n");
131*1da177e4SLinus Torvalds shost_rd_attr(unchecked_isa_dma, "%d\n");
132*1da177e4SLinus Torvalds shost_rd_attr2(proc_name, hostt->proc_name, "%s\n");
133*1da177e4SLinus Torvalds 
134*1da177e4SLinus Torvalds static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
135*1da177e4SLinus Torvalds 	&class_device_attr_unique_id,
136*1da177e4SLinus Torvalds 	&class_device_attr_host_busy,
137*1da177e4SLinus Torvalds 	&class_device_attr_cmd_per_lun,
138*1da177e4SLinus Torvalds 	&class_device_attr_sg_tablesize,
139*1da177e4SLinus Torvalds 	&class_device_attr_unchecked_isa_dma,
140*1da177e4SLinus Torvalds 	&class_device_attr_proc_name,
141*1da177e4SLinus Torvalds 	&class_device_attr_scan,
142*1da177e4SLinus Torvalds 	NULL
143*1da177e4SLinus Torvalds };
144*1da177e4SLinus Torvalds 
145*1da177e4SLinus Torvalds static void scsi_device_cls_release(struct class_device *class_dev)
146*1da177e4SLinus Torvalds {
147*1da177e4SLinus Torvalds 	struct scsi_device *sdev;
148*1da177e4SLinus Torvalds 
149*1da177e4SLinus Torvalds 	sdev = class_to_sdev(class_dev);
150*1da177e4SLinus Torvalds 	put_device(&sdev->sdev_gendev);
151*1da177e4SLinus Torvalds }
152*1da177e4SLinus Torvalds 
153*1da177e4SLinus Torvalds void scsi_device_dev_release(struct device *dev)
154*1da177e4SLinus Torvalds {
155*1da177e4SLinus Torvalds 	struct scsi_device *sdev;
156*1da177e4SLinus Torvalds 	struct device *parent;
157*1da177e4SLinus Torvalds 	struct scsi_target *starget;
158*1da177e4SLinus Torvalds 	unsigned long flags;
159*1da177e4SLinus Torvalds 
160*1da177e4SLinus Torvalds 	parent = dev->parent;
161*1da177e4SLinus Torvalds 	sdev = to_scsi_device(dev);
162*1da177e4SLinus Torvalds 	starget = to_scsi_target(parent);
163*1da177e4SLinus Torvalds 
164*1da177e4SLinus Torvalds 	spin_lock_irqsave(sdev->host->host_lock, flags);
165*1da177e4SLinus Torvalds 	starget->reap_ref++;
166*1da177e4SLinus Torvalds 	list_del(&sdev->siblings);
167*1da177e4SLinus Torvalds 	list_del(&sdev->same_target_siblings);
168*1da177e4SLinus Torvalds 	list_del(&sdev->starved_entry);
169*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(sdev->host->host_lock, flags);
170*1da177e4SLinus Torvalds 
171*1da177e4SLinus Torvalds 	if (sdev->request_queue) {
172*1da177e4SLinus Torvalds 		sdev->request_queue->queuedata = NULL;
173*1da177e4SLinus Torvalds 		scsi_free_queue(sdev->request_queue);
174*1da177e4SLinus Torvalds 	}
175*1da177e4SLinus Torvalds 
176*1da177e4SLinus Torvalds 	scsi_target_reap(scsi_target(sdev));
177*1da177e4SLinus Torvalds 
178*1da177e4SLinus Torvalds 	kfree(sdev->inquiry);
179*1da177e4SLinus Torvalds 	kfree(sdev);
180*1da177e4SLinus Torvalds 
181*1da177e4SLinus Torvalds 	if (parent)
182*1da177e4SLinus Torvalds 		put_device(parent);
183*1da177e4SLinus Torvalds }
184*1da177e4SLinus Torvalds 
185*1da177e4SLinus Torvalds struct class sdev_class = {
186*1da177e4SLinus Torvalds 	.name		= "scsi_device",
187*1da177e4SLinus Torvalds 	.release	= scsi_device_cls_release,
188*1da177e4SLinus Torvalds };
189*1da177e4SLinus Torvalds 
190*1da177e4SLinus Torvalds /* all probing is done in the individual ->probe routines */
191*1da177e4SLinus Torvalds static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
192*1da177e4SLinus Torvalds {
193*1da177e4SLinus Torvalds 	struct scsi_device *sdp = to_scsi_device(dev);
194*1da177e4SLinus Torvalds 	if (sdp->no_uld_attach)
195*1da177e4SLinus Torvalds 		return 0;
196*1da177e4SLinus Torvalds 	return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
197*1da177e4SLinus Torvalds }
198*1da177e4SLinus Torvalds 
199*1da177e4SLinus Torvalds struct bus_type scsi_bus_type = {
200*1da177e4SLinus Torvalds         .name		= "scsi",
201*1da177e4SLinus Torvalds         .match		= scsi_bus_match,
202*1da177e4SLinus Torvalds };
203*1da177e4SLinus Torvalds 
204*1da177e4SLinus Torvalds int scsi_sysfs_register(void)
205*1da177e4SLinus Torvalds {
206*1da177e4SLinus Torvalds 	int error;
207*1da177e4SLinus Torvalds 
208*1da177e4SLinus Torvalds 	error = bus_register(&scsi_bus_type);
209*1da177e4SLinus Torvalds 	if (!error) {
210*1da177e4SLinus Torvalds 		error = class_register(&sdev_class);
211*1da177e4SLinus Torvalds 		if (error)
212*1da177e4SLinus Torvalds 			bus_unregister(&scsi_bus_type);
213*1da177e4SLinus Torvalds 	}
214*1da177e4SLinus Torvalds 
215*1da177e4SLinus Torvalds 	return error;
216*1da177e4SLinus Torvalds }
217*1da177e4SLinus Torvalds 
218*1da177e4SLinus Torvalds void scsi_sysfs_unregister(void)
219*1da177e4SLinus Torvalds {
220*1da177e4SLinus Torvalds 	class_unregister(&sdev_class);
221*1da177e4SLinus Torvalds 	bus_unregister(&scsi_bus_type);
222*1da177e4SLinus Torvalds }
223*1da177e4SLinus Torvalds 
224*1da177e4SLinus Torvalds /*
225*1da177e4SLinus Torvalds  * sdev_show_function: macro to create an attr function that can be used to
226*1da177e4SLinus Torvalds  * show a non-bit field.
227*1da177e4SLinus Torvalds  */
228*1da177e4SLinus Torvalds #define sdev_show_function(field, format_string)				\
229*1da177e4SLinus Torvalds static ssize_t								\
230*1da177e4SLinus Torvalds sdev_show_##field (struct device *dev, char *buf)				\
231*1da177e4SLinus Torvalds {									\
232*1da177e4SLinus Torvalds 	struct scsi_device *sdev;					\
233*1da177e4SLinus Torvalds 	sdev = to_scsi_device(dev);					\
234*1da177e4SLinus Torvalds 	return snprintf (buf, 20, format_string, sdev->field);		\
235*1da177e4SLinus Torvalds }									\
236*1da177e4SLinus Torvalds 
237*1da177e4SLinus Torvalds /*
238*1da177e4SLinus Torvalds  * sdev_rd_attr: macro to create a function and attribute variable for a
239*1da177e4SLinus Torvalds  * read only field.
240*1da177e4SLinus Torvalds  */
241*1da177e4SLinus Torvalds #define sdev_rd_attr(field, format_string)				\
242*1da177e4SLinus Torvalds 	sdev_show_function(field, format_string)			\
243*1da177e4SLinus Torvalds static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL);
244*1da177e4SLinus Torvalds 
245*1da177e4SLinus Torvalds 
246*1da177e4SLinus Torvalds /*
247*1da177e4SLinus Torvalds  * sdev_rd_attr: create a function and attribute variable for a
248*1da177e4SLinus Torvalds  * read/write field.
249*1da177e4SLinus Torvalds  */
250*1da177e4SLinus Torvalds #define sdev_rw_attr(field, format_string)				\
251*1da177e4SLinus Torvalds 	sdev_show_function(field, format_string)				\
252*1da177e4SLinus Torvalds 									\
253*1da177e4SLinus Torvalds static ssize_t								\
254*1da177e4SLinus Torvalds sdev_store_##field (struct device *dev, const char *buf, size_t count)	\
255*1da177e4SLinus Torvalds {									\
256*1da177e4SLinus Torvalds 	struct scsi_device *sdev;					\
257*1da177e4SLinus Torvalds 	sdev = to_scsi_device(dev);					\
258*1da177e4SLinus Torvalds 	snscanf (buf, 20, format_string, &sdev->field);			\
259*1da177e4SLinus Torvalds 	return count;							\
260*1da177e4SLinus Torvalds }									\
261*1da177e4SLinus Torvalds static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
262*1da177e4SLinus Torvalds 
263*1da177e4SLinus Torvalds /* Currently we don't export bit fields, but we might in future,
264*1da177e4SLinus Torvalds  * so leave this code in */
265*1da177e4SLinus Torvalds #if 0
266*1da177e4SLinus Torvalds /*
267*1da177e4SLinus Torvalds  * sdev_rd_attr: create a function and attribute variable for a
268*1da177e4SLinus Torvalds  * read/write bit field.
269*1da177e4SLinus Torvalds  */
270*1da177e4SLinus Torvalds #define sdev_rw_attr_bit(field)						\
271*1da177e4SLinus Torvalds 	sdev_show_function(field, "%d\n")					\
272*1da177e4SLinus Torvalds 									\
273*1da177e4SLinus Torvalds static ssize_t								\
274*1da177e4SLinus Torvalds sdev_store_##field (struct device *dev, const char *buf, size_t count)	\
275*1da177e4SLinus Torvalds {									\
276*1da177e4SLinus Torvalds 	int ret;							\
277*1da177e4SLinus Torvalds 	struct scsi_device *sdev;					\
278*1da177e4SLinus Torvalds 	ret = scsi_sdev_check_buf_bit(buf);				\
279*1da177e4SLinus Torvalds 	if (ret >= 0)	{						\
280*1da177e4SLinus Torvalds 		sdev = to_scsi_device(dev);				\
281*1da177e4SLinus Torvalds 		sdev->field = ret;					\
282*1da177e4SLinus Torvalds 		ret = count;						\
283*1da177e4SLinus Torvalds 	}								\
284*1da177e4SLinus Torvalds 	return ret;							\
285*1da177e4SLinus Torvalds }									\
286*1da177e4SLinus Torvalds static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
287*1da177e4SLinus Torvalds 
288*1da177e4SLinus Torvalds /*
289*1da177e4SLinus Torvalds  * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
290*1da177e4SLinus Torvalds  * else return -EINVAL.
291*1da177e4SLinus Torvalds  */
292*1da177e4SLinus Torvalds static int scsi_sdev_check_buf_bit(const char *buf)
293*1da177e4SLinus Torvalds {
294*1da177e4SLinus Torvalds 	if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
295*1da177e4SLinus Torvalds 		if (buf[0] == '1')
296*1da177e4SLinus Torvalds 			return 1;
297*1da177e4SLinus Torvalds 		else if (buf[0] == '0')
298*1da177e4SLinus Torvalds 			return 0;
299*1da177e4SLinus Torvalds 		else
300*1da177e4SLinus Torvalds 			return -EINVAL;
301*1da177e4SLinus Torvalds 	} else
302*1da177e4SLinus Torvalds 		return -EINVAL;
303*1da177e4SLinus Torvalds }
304*1da177e4SLinus Torvalds #endif
305*1da177e4SLinus Torvalds /*
306*1da177e4SLinus Torvalds  * Create the actual show/store functions and data structures.
307*1da177e4SLinus Torvalds  */
308*1da177e4SLinus Torvalds sdev_rd_attr (device_blocked, "%d\n");
309*1da177e4SLinus Torvalds sdev_rd_attr (queue_depth, "%d\n");
310*1da177e4SLinus Torvalds sdev_rd_attr (type, "%d\n");
311*1da177e4SLinus Torvalds sdev_rd_attr (scsi_level, "%d\n");
312*1da177e4SLinus Torvalds sdev_rd_attr (vendor, "%.8s\n");
313*1da177e4SLinus Torvalds sdev_rd_attr (model, "%.16s\n");
314*1da177e4SLinus Torvalds sdev_rd_attr (rev, "%.4s\n");
315*1da177e4SLinus Torvalds 
316*1da177e4SLinus Torvalds static ssize_t
317*1da177e4SLinus Torvalds sdev_show_timeout (struct device *dev, char *buf)
318*1da177e4SLinus Torvalds {
319*1da177e4SLinus Torvalds 	struct scsi_device *sdev;
320*1da177e4SLinus Torvalds 	sdev = to_scsi_device(dev);
321*1da177e4SLinus Torvalds 	return snprintf (buf, 20, "%d\n", sdev->timeout / HZ);
322*1da177e4SLinus Torvalds }
323*1da177e4SLinus Torvalds 
324*1da177e4SLinus Torvalds static ssize_t
325*1da177e4SLinus Torvalds sdev_store_timeout (struct device *dev, const char *buf, size_t count)
326*1da177e4SLinus Torvalds {
327*1da177e4SLinus Torvalds 	struct scsi_device *sdev;
328*1da177e4SLinus Torvalds 	int timeout;
329*1da177e4SLinus Torvalds 	sdev = to_scsi_device(dev);
330*1da177e4SLinus Torvalds 	sscanf (buf, "%d\n", &timeout);
331*1da177e4SLinus Torvalds 	sdev->timeout = timeout * HZ;
332*1da177e4SLinus Torvalds 	return count;
333*1da177e4SLinus Torvalds }
334*1da177e4SLinus Torvalds static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
335*1da177e4SLinus Torvalds 
336*1da177e4SLinus Torvalds static ssize_t
337*1da177e4SLinus Torvalds store_rescan_field (struct device *dev, const char *buf, size_t count)
338*1da177e4SLinus Torvalds {
339*1da177e4SLinus Torvalds 	scsi_rescan_device(dev);
340*1da177e4SLinus Torvalds 	return count;
341*1da177e4SLinus Torvalds }
342*1da177e4SLinus Torvalds static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
343*1da177e4SLinus Torvalds 
344*1da177e4SLinus Torvalds static ssize_t sdev_store_delete(struct device *dev, const char *buf,
345*1da177e4SLinus Torvalds 				 size_t count)
346*1da177e4SLinus Torvalds {
347*1da177e4SLinus Torvalds 	scsi_remove_device(to_scsi_device(dev));
348*1da177e4SLinus Torvalds 	return count;
349*1da177e4SLinus Torvalds };
350*1da177e4SLinus Torvalds static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
351*1da177e4SLinus Torvalds 
352*1da177e4SLinus Torvalds static ssize_t
353*1da177e4SLinus Torvalds store_state_field(struct device *dev, const char *buf, size_t count)
354*1da177e4SLinus Torvalds {
355*1da177e4SLinus Torvalds 	int i;
356*1da177e4SLinus Torvalds 	struct scsi_device *sdev = to_scsi_device(dev);
357*1da177e4SLinus Torvalds 	enum scsi_device_state state = 0;
358*1da177e4SLinus Torvalds 
359*1da177e4SLinus Torvalds 	for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) {
360*1da177e4SLinus Torvalds 		const int len = strlen(sdev_states[i].name);
361*1da177e4SLinus Torvalds 		if (strncmp(sdev_states[i].name, buf, len) == 0 &&
362*1da177e4SLinus Torvalds 		   buf[len] == '\n') {
363*1da177e4SLinus Torvalds 			state = sdev_states[i].value;
364*1da177e4SLinus Torvalds 			break;
365*1da177e4SLinus Torvalds 		}
366*1da177e4SLinus Torvalds 	}
367*1da177e4SLinus Torvalds 	if (!state)
368*1da177e4SLinus Torvalds 		return -EINVAL;
369*1da177e4SLinus Torvalds 
370*1da177e4SLinus Torvalds 	if (scsi_device_set_state(sdev, state))
371*1da177e4SLinus Torvalds 		return -EINVAL;
372*1da177e4SLinus Torvalds 	return count;
373*1da177e4SLinus Torvalds }
374*1da177e4SLinus Torvalds 
375*1da177e4SLinus Torvalds static ssize_t
376*1da177e4SLinus Torvalds show_state_field(struct device *dev, char *buf)
377*1da177e4SLinus Torvalds {
378*1da177e4SLinus Torvalds 	struct scsi_device *sdev = to_scsi_device(dev);
379*1da177e4SLinus Torvalds 	const char *name = scsi_device_state_name(sdev->sdev_state);
380*1da177e4SLinus Torvalds 
381*1da177e4SLinus Torvalds 	if (!name)
382*1da177e4SLinus Torvalds 		return -EINVAL;
383*1da177e4SLinus Torvalds 
384*1da177e4SLinus Torvalds 	return snprintf(buf, 20, "%s\n", name);
385*1da177e4SLinus Torvalds }
386*1da177e4SLinus Torvalds 
387*1da177e4SLinus Torvalds static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
388*1da177e4SLinus Torvalds 
389*1da177e4SLinus Torvalds static ssize_t
390*1da177e4SLinus Torvalds show_queue_type_field(struct device *dev, char *buf)
391*1da177e4SLinus Torvalds {
392*1da177e4SLinus Torvalds 	struct scsi_device *sdev = to_scsi_device(dev);
393*1da177e4SLinus Torvalds 	const char *name = "none";
394*1da177e4SLinus Torvalds 
395*1da177e4SLinus Torvalds 	if (sdev->ordered_tags)
396*1da177e4SLinus Torvalds 		name = "ordered";
397*1da177e4SLinus Torvalds 	else if (sdev->simple_tags)
398*1da177e4SLinus Torvalds 		name = "simple";
399*1da177e4SLinus Torvalds 
400*1da177e4SLinus Torvalds 	return snprintf(buf, 20, "%s\n", name);
401*1da177e4SLinus Torvalds }
402*1da177e4SLinus Torvalds 
403*1da177e4SLinus Torvalds static DEVICE_ATTR(queue_type, S_IRUGO, show_queue_type_field, NULL);
404*1da177e4SLinus Torvalds 
405*1da177e4SLinus Torvalds static ssize_t
406*1da177e4SLinus Torvalds show_iostat_counterbits(struct device *dev, char *buf)
407*1da177e4SLinus Torvalds {
408*1da177e4SLinus Torvalds 	return snprintf(buf, 20, "%d\n", (int)sizeof(atomic_t) * 8);
409*1da177e4SLinus Torvalds }
410*1da177e4SLinus Torvalds 
411*1da177e4SLinus Torvalds static DEVICE_ATTR(iocounterbits, S_IRUGO, show_iostat_counterbits, NULL);
412*1da177e4SLinus Torvalds 
413*1da177e4SLinus Torvalds #define show_sdev_iostat(field)						\
414*1da177e4SLinus Torvalds static ssize_t								\
415*1da177e4SLinus Torvalds show_iostat_##field(struct device *dev, char *buf)			\
416*1da177e4SLinus Torvalds {									\
417*1da177e4SLinus Torvalds 	struct scsi_device *sdev = to_scsi_device(dev);			\
418*1da177e4SLinus Torvalds 	unsigned long long count = atomic_read(&sdev->field);		\
419*1da177e4SLinus Torvalds 	return snprintf(buf, 20, "0x%llx\n", count);			\
420*1da177e4SLinus Torvalds }									\
421*1da177e4SLinus Torvalds static DEVICE_ATTR(field, S_IRUGO, show_iostat_##field, NULL)
422*1da177e4SLinus Torvalds 
423*1da177e4SLinus Torvalds show_sdev_iostat(iorequest_cnt);
424*1da177e4SLinus Torvalds show_sdev_iostat(iodone_cnt);
425*1da177e4SLinus Torvalds show_sdev_iostat(ioerr_cnt);
426*1da177e4SLinus Torvalds 
427*1da177e4SLinus Torvalds 
428*1da177e4SLinus Torvalds /* Default template for device attributes.  May NOT be modified */
429*1da177e4SLinus Torvalds static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
430*1da177e4SLinus Torvalds 	&dev_attr_device_blocked,
431*1da177e4SLinus Torvalds 	&dev_attr_queue_depth,
432*1da177e4SLinus Torvalds 	&dev_attr_queue_type,
433*1da177e4SLinus Torvalds 	&dev_attr_type,
434*1da177e4SLinus Torvalds 	&dev_attr_scsi_level,
435*1da177e4SLinus Torvalds 	&dev_attr_vendor,
436*1da177e4SLinus Torvalds 	&dev_attr_model,
437*1da177e4SLinus Torvalds 	&dev_attr_rev,
438*1da177e4SLinus Torvalds 	&dev_attr_rescan,
439*1da177e4SLinus Torvalds 	&dev_attr_delete,
440*1da177e4SLinus Torvalds 	&dev_attr_state,
441*1da177e4SLinus Torvalds 	&dev_attr_timeout,
442*1da177e4SLinus Torvalds 	&dev_attr_iocounterbits,
443*1da177e4SLinus Torvalds 	&dev_attr_iorequest_cnt,
444*1da177e4SLinus Torvalds 	&dev_attr_iodone_cnt,
445*1da177e4SLinus Torvalds 	&dev_attr_ioerr_cnt,
446*1da177e4SLinus Torvalds 	NULL
447*1da177e4SLinus Torvalds };
448*1da177e4SLinus Torvalds 
449*1da177e4SLinus Torvalds static ssize_t sdev_store_queue_depth_rw(struct device *dev, const char *buf,
450*1da177e4SLinus Torvalds 					 size_t count)
451*1da177e4SLinus Torvalds {
452*1da177e4SLinus Torvalds 	int depth, retval;
453*1da177e4SLinus Torvalds 	struct scsi_device *sdev = to_scsi_device(dev);
454*1da177e4SLinus Torvalds 	struct scsi_host_template *sht = sdev->host->hostt;
455*1da177e4SLinus Torvalds 
456*1da177e4SLinus Torvalds 	if (!sht->change_queue_depth)
457*1da177e4SLinus Torvalds 		return -EINVAL;
458*1da177e4SLinus Torvalds 
459*1da177e4SLinus Torvalds 	depth = simple_strtoul(buf, NULL, 0);
460*1da177e4SLinus Torvalds 
461*1da177e4SLinus Torvalds 	if (depth < 1)
462*1da177e4SLinus Torvalds 		return -EINVAL;
463*1da177e4SLinus Torvalds 
464*1da177e4SLinus Torvalds 	retval = sht->change_queue_depth(sdev, depth);
465*1da177e4SLinus Torvalds 	if (retval < 0)
466*1da177e4SLinus Torvalds 		return retval;
467*1da177e4SLinus Torvalds 
468*1da177e4SLinus Torvalds 	return count;
469*1da177e4SLinus Torvalds }
470*1da177e4SLinus Torvalds 
471*1da177e4SLinus Torvalds static struct device_attribute sdev_attr_queue_depth_rw =
472*1da177e4SLinus Torvalds 	__ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
473*1da177e4SLinus Torvalds 	       sdev_store_queue_depth_rw);
474*1da177e4SLinus Torvalds 
475*1da177e4SLinus Torvalds static ssize_t sdev_store_queue_type_rw(struct device *dev, const char *buf,
476*1da177e4SLinus Torvalds 					size_t count)
477*1da177e4SLinus Torvalds {
478*1da177e4SLinus Torvalds 	struct scsi_device *sdev = to_scsi_device(dev);
479*1da177e4SLinus Torvalds 	struct scsi_host_template *sht = sdev->host->hostt;
480*1da177e4SLinus Torvalds 	int tag_type = 0, retval;
481*1da177e4SLinus Torvalds 	int prev_tag_type = scsi_get_tag_type(sdev);
482*1da177e4SLinus Torvalds 
483*1da177e4SLinus Torvalds 	if (!sdev->tagged_supported || !sht->change_queue_type)
484*1da177e4SLinus Torvalds 		return -EINVAL;
485*1da177e4SLinus Torvalds 
486*1da177e4SLinus Torvalds 	if (strncmp(buf, "ordered", 7) == 0)
487*1da177e4SLinus Torvalds 		tag_type = MSG_ORDERED_TAG;
488*1da177e4SLinus Torvalds 	else if (strncmp(buf, "simple", 6) == 0)
489*1da177e4SLinus Torvalds 		tag_type = MSG_SIMPLE_TAG;
490*1da177e4SLinus Torvalds 	else if (strncmp(buf, "none", 4) != 0)
491*1da177e4SLinus Torvalds 		return -EINVAL;
492*1da177e4SLinus Torvalds 
493*1da177e4SLinus Torvalds 	if (tag_type == prev_tag_type)
494*1da177e4SLinus Torvalds 		return count;
495*1da177e4SLinus Torvalds 
496*1da177e4SLinus Torvalds 	retval = sht->change_queue_type(sdev, tag_type);
497*1da177e4SLinus Torvalds 	if (retval < 0)
498*1da177e4SLinus Torvalds 		return retval;
499*1da177e4SLinus Torvalds 
500*1da177e4SLinus Torvalds 	return count;
501*1da177e4SLinus Torvalds }
502*1da177e4SLinus Torvalds 
503*1da177e4SLinus Torvalds static struct device_attribute sdev_attr_queue_type_rw =
504*1da177e4SLinus Torvalds 	__ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
505*1da177e4SLinus Torvalds 	       sdev_store_queue_type_rw);
506*1da177e4SLinus Torvalds 
507*1da177e4SLinus Torvalds static struct device_attribute *attr_changed_internally(
508*1da177e4SLinus Torvalds 		struct Scsi_Host *shost,
509*1da177e4SLinus Torvalds 		struct device_attribute * attr)
510*1da177e4SLinus Torvalds {
511*1da177e4SLinus Torvalds 	if (!strcmp("queue_depth", attr->attr.name)
512*1da177e4SLinus Torvalds 	    && shost->hostt->change_queue_depth)
513*1da177e4SLinus Torvalds 		return &sdev_attr_queue_depth_rw;
514*1da177e4SLinus Torvalds 	else if (!strcmp("queue_type", attr->attr.name)
515*1da177e4SLinus Torvalds 	    && shost->hostt->change_queue_type)
516*1da177e4SLinus Torvalds 		return &sdev_attr_queue_type_rw;
517*1da177e4SLinus Torvalds 	return attr;
518*1da177e4SLinus Torvalds }
519*1da177e4SLinus Torvalds 
520*1da177e4SLinus Torvalds 
521*1da177e4SLinus Torvalds static struct device_attribute *attr_overridden(
522*1da177e4SLinus Torvalds 		struct device_attribute **attrs,
523*1da177e4SLinus Torvalds 		struct device_attribute *attr)
524*1da177e4SLinus Torvalds {
525*1da177e4SLinus Torvalds 	int i;
526*1da177e4SLinus Torvalds 
527*1da177e4SLinus Torvalds 	if (!attrs)
528*1da177e4SLinus Torvalds 		return NULL;
529*1da177e4SLinus Torvalds 	for (i = 0; attrs[i]; i++)
530*1da177e4SLinus Torvalds 		if (!strcmp(attrs[i]->attr.name, attr->attr.name))
531*1da177e4SLinus Torvalds 			return attrs[i];
532*1da177e4SLinus Torvalds 	return NULL;
533*1da177e4SLinus Torvalds }
534*1da177e4SLinus Torvalds 
535*1da177e4SLinus Torvalds static int attr_add(struct device *dev, struct device_attribute *attr)
536*1da177e4SLinus Torvalds {
537*1da177e4SLinus Torvalds 	struct device_attribute *base_attr;
538*1da177e4SLinus Torvalds 
539*1da177e4SLinus Torvalds 	/*
540*1da177e4SLinus Torvalds 	 * Spare the caller from having to copy things it's not interested in.
541*1da177e4SLinus Torvalds 	 */
542*1da177e4SLinus Torvalds 	base_attr = attr_overridden(scsi_sysfs_sdev_attrs, attr);
543*1da177e4SLinus Torvalds 	if (base_attr) {
544*1da177e4SLinus Torvalds 		/* extend permissions */
545*1da177e4SLinus Torvalds 		attr->attr.mode |= base_attr->attr.mode;
546*1da177e4SLinus Torvalds 
547*1da177e4SLinus Torvalds 		/* override null show/store with default */
548*1da177e4SLinus Torvalds 		if (!attr->show)
549*1da177e4SLinus Torvalds 			attr->show = base_attr->show;
550*1da177e4SLinus Torvalds 		if (!attr->store)
551*1da177e4SLinus Torvalds 			attr->store = base_attr->store;
552*1da177e4SLinus Torvalds 	}
553*1da177e4SLinus Torvalds 
554*1da177e4SLinus Torvalds 	return device_create_file(dev, attr);
555*1da177e4SLinus Torvalds }
556*1da177e4SLinus Torvalds 
557*1da177e4SLinus Torvalds /**
558*1da177e4SLinus Torvalds  * scsi_sysfs_add_sdev - add scsi device to sysfs
559*1da177e4SLinus Torvalds  * @sdev:	scsi_device to add
560*1da177e4SLinus Torvalds  *
561*1da177e4SLinus Torvalds  * Return value:
562*1da177e4SLinus Torvalds  * 	0 on Success / non-zero on Failure
563*1da177e4SLinus Torvalds  **/
564*1da177e4SLinus Torvalds int scsi_sysfs_add_sdev(struct scsi_device *sdev)
565*1da177e4SLinus Torvalds {
566*1da177e4SLinus Torvalds 	int error, i;
567*1da177e4SLinus Torvalds 
568*1da177e4SLinus Torvalds 	if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
569*1da177e4SLinus Torvalds 		return error;
570*1da177e4SLinus Torvalds 
571*1da177e4SLinus Torvalds 	error = device_add(&sdev->sdev_gendev);
572*1da177e4SLinus Torvalds 	if (error) {
573*1da177e4SLinus Torvalds 		put_device(sdev->sdev_gendev.parent);
574*1da177e4SLinus Torvalds 		printk(KERN_INFO "error 1\n");
575*1da177e4SLinus Torvalds 		return error;
576*1da177e4SLinus Torvalds 	}
577*1da177e4SLinus Torvalds 	error = class_device_add(&sdev->sdev_classdev);
578*1da177e4SLinus Torvalds 	if (error) {
579*1da177e4SLinus Torvalds 		printk(KERN_INFO "error 2\n");
580*1da177e4SLinus Torvalds 		goto clean_device;
581*1da177e4SLinus Torvalds 	}
582*1da177e4SLinus Torvalds 
583*1da177e4SLinus Torvalds 	/* take a reference for the sdev_classdev; this is
584*1da177e4SLinus Torvalds 	 * released by the sdev_class .release */
585*1da177e4SLinus Torvalds 	get_device(&sdev->sdev_gendev);
586*1da177e4SLinus Torvalds 	if (sdev->host->hostt->sdev_attrs) {
587*1da177e4SLinus Torvalds 		for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
588*1da177e4SLinus Torvalds 			error = attr_add(&sdev->sdev_gendev,
589*1da177e4SLinus Torvalds 					sdev->host->hostt->sdev_attrs[i]);
590*1da177e4SLinus Torvalds 			if (error) {
591*1da177e4SLinus Torvalds 				scsi_remove_device(sdev);
592*1da177e4SLinus Torvalds 				goto out;
593*1da177e4SLinus Torvalds 			}
594*1da177e4SLinus Torvalds 		}
595*1da177e4SLinus Torvalds 	}
596*1da177e4SLinus Torvalds 
597*1da177e4SLinus Torvalds 	for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) {
598*1da177e4SLinus Torvalds 		if (!attr_overridden(sdev->host->hostt->sdev_attrs,
599*1da177e4SLinus Torvalds 					scsi_sysfs_sdev_attrs[i])) {
600*1da177e4SLinus Torvalds 			struct device_attribute * attr =
601*1da177e4SLinus Torvalds 				attr_changed_internally(sdev->host,
602*1da177e4SLinus Torvalds 							scsi_sysfs_sdev_attrs[i]);
603*1da177e4SLinus Torvalds 			error = device_create_file(&sdev->sdev_gendev, attr);
604*1da177e4SLinus Torvalds 			if (error) {
605*1da177e4SLinus Torvalds 				scsi_remove_device(sdev);
606*1da177e4SLinus Torvalds 				goto out;
607*1da177e4SLinus Torvalds 			}
608*1da177e4SLinus Torvalds 		}
609*1da177e4SLinus Torvalds 	}
610*1da177e4SLinus Torvalds 
611*1da177e4SLinus Torvalds 	transport_add_device(&sdev->sdev_gendev);
612*1da177e4SLinus Torvalds  out:
613*1da177e4SLinus Torvalds 	return error;
614*1da177e4SLinus Torvalds 
615*1da177e4SLinus Torvalds  clean_device:
616*1da177e4SLinus Torvalds 	scsi_device_set_state(sdev, SDEV_CANCEL);
617*1da177e4SLinus Torvalds 
618*1da177e4SLinus Torvalds 	device_del(&sdev->sdev_gendev);
619*1da177e4SLinus Torvalds 	transport_destroy_device(&sdev->sdev_gendev);
620*1da177e4SLinus Torvalds 	put_device(&sdev->sdev_gendev);
621*1da177e4SLinus Torvalds 
622*1da177e4SLinus Torvalds 	return error;
623*1da177e4SLinus Torvalds }
624*1da177e4SLinus Torvalds 
625*1da177e4SLinus Torvalds /**
626*1da177e4SLinus Torvalds  * scsi_remove_device - unregister a device from the scsi bus
627*1da177e4SLinus Torvalds  * @sdev:	scsi_device to unregister
628*1da177e4SLinus Torvalds  **/
629*1da177e4SLinus Torvalds void scsi_remove_device(struct scsi_device *sdev)
630*1da177e4SLinus Torvalds {
631*1da177e4SLinus Torvalds 	struct Scsi_Host *shost = sdev->host;
632*1da177e4SLinus Torvalds 
633*1da177e4SLinus Torvalds 	down(&shost->scan_mutex);
634*1da177e4SLinus Torvalds 	if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
635*1da177e4SLinus Torvalds 		goto out;
636*1da177e4SLinus Torvalds 
637*1da177e4SLinus Torvalds 	class_device_unregister(&sdev->sdev_classdev);
638*1da177e4SLinus Torvalds 	device_del(&sdev->sdev_gendev);
639*1da177e4SLinus Torvalds 	scsi_device_set_state(sdev, SDEV_DEL);
640*1da177e4SLinus Torvalds 	if (sdev->host->hostt->slave_destroy)
641*1da177e4SLinus Torvalds 		sdev->host->hostt->slave_destroy(sdev);
642*1da177e4SLinus Torvalds 	transport_unregister_device(&sdev->sdev_gendev);
643*1da177e4SLinus Torvalds 	put_device(&sdev->sdev_gendev);
644*1da177e4SLinus Torvalds out:
645*1da177e4SLinus Torvalds 	up(&shost->scan_mutex);
646*1da177e4SLinus Torvalds }
647*1da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_remove_device);
648*1da177e4SLinus Torvalds 
649*1da177e4SLinus Torvalds void __scsi_remove_target(struct scsi_target *starget)
650*1da177e4SLinus Torvalds {
651*1da177e4SLinus Torvalds 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
652*1da177e4SLinus Torvalds 	unsigned long flags;
653*1da177e4SLinus Torvalds 	struct scsi_device *sdev, *tmp;
654*1da177e4SLinus Torvalds 
655*1da177e4SLinus Torvalds 	spin_lock_irqsave(shost->host_lock, flags);
656*1da177e4SLinus Torvalds 	starget->reap_ref++;
657*1da177e4SLinus Torvalds 	list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) {
658*1da177e4SLinus Torvalds 		if (sdev->channel != starget->channel ||
659*1da177e4SLinus Torvalds 		    sdev->id != starget->id)
660*1da177e4SLinus Torvalds 			continue;
661*1da177e4SLinus Torvalds 		spin_unlock_irqrestore(shost->host_lock, flags);
662*1da177e4SLinus Torvalds 		scsi_remove_device(sdev);
663*1da177e4SLinus Torvalds 		spin_lock_irqsave(shost->host_lock, flags);
664*1da177e4SLinus Torvalds 	}
665*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(shost->host_lock, flags);
666*1da177e4SLinus Torvalds 	scsi_target_reap(starget);
667*1da177e4SLinus Torvalds }
668*1da177e4SLinus Torvalds 
669*1da177e4SLinus Torvalds /**
670*1da177e4SLinus Torvalds  * scsi_remove_target - try to remove a target and all its devices
671*1da177e4SLinus Torvalds  * @dev: generic starget or parent of generic stargets to be removed
672*1da177e4SLinus Torvalds  *
673*1da177e4SLinus Torvalds  * Note: This is slightly racy.  It is possible that if the user
674*1da177e4SLinus Torvalds  * requests the addition of another device then the target won't be
675*1da177e4SLinus Torvalds  * removed.
676*1da177e4SLinus Torvalds  */
677*1da177e4SLinus Torvalds void scsi_remove_target(struct device *dev)
678*1da177e4SLinus Torvalds {
679*1da177e4SLinus Torvalds 	struct device *rdev, *idev, *next;
680*1da177e4SLinus Torvalds 
681*1da177e4SLinus Torvalds 	if (scsi_is_target_device(dev)) {
682*1da177e4SLinus Torvalds 		__scsi_remove_target(to_scsi_target(dev));
683*1da177e4SLinus Torvalds 		return;
684*1da177e4SLinus Torvalds 	}
685*1da177e4SLinus Torvalds 
686*1da177e4SLinus Torvalds 	rdev = get_device(dev);
687*1da177e4SLinus Torvalds 	list_for_each_entry_safe(idev, next, &dev->children, node) {
688*1da177e4SLinus Torvalds 		if (scsi_is_target_device(idev))
689*1da177e4SLinus Torvalds 			__scsi_remove_target(to_scsi_target(idev));
690*1da177e4SLinus Torvalds 	}
691*1da177e4SLinus Torvalds 	put_device(rdev);
692*1da177e4SLinus Torvalds }
693*1da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_remove_target);
694*1da177e4SLinus Torvalds 
695*1da177e4SLinus Torvalds int scsi_register_driver(struct device_driver *drv)
696*1da177e4SLinus Torvalds {
697*1da177e4SLinus Torvalds 	drv->bus = &scsi_bus_type;
698*1da177e4SLinus Torvalds 
699*1da177e4SLinus Torvalds 	return driver_register(drv);
700*1da177e4SLinus Torvalds }
701*1da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_register_driver);
702*1da177e4SLinus Torvalds 
703*1da177e4SLinus Torvalds int scsi_register_interface(struct class_interface *intf)
704*1da177e4SLinus Torvalds {
705*1da177e4SLinus Torvalds 	intf->class = &sdev_class;
706*1da177e4SLinus Torvalds 
707*1da177e4SLinus Torvalds 	return class_interface_register(intf);
708*1da177e4SLinus Torvalds }
709*1da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_register_interface);
710*1da177e4SLinus Torvalds 
711*1da177e4SLinus Torvalds 
712*1da177e4SLinus Torvalds static struct class_device_attribute *class_attr_overridden(
713*1da177e4SLinus Torvalds 		struct class_device_attribute **attrs,
714*1da177e4SLinus Torvalds 		struct class_device_attribute *attr)
715*1da177e4SLinus Torvalds {
716*1da177e4SLinus Torvalds 	int i;
717*1da177e4SLinus Torvalds 
718*1da177e4SLinus Torvalds 	if (!attrs)
719*1da177e4SLinus Torvalds 		return NULL;
720*1da177e4SLinus Torvalds 	for (i = 0; attrs[i]; i++)
721*1da177e4SLinus Torvalds 		if (!strcmp(attrs[i]->attr.name, attr->attr.name))
722*1da177e4SLinus Torvalds 			return attrs[i];
723*1da177e4SLinus Torvalds 	return NULL;
724*1da177e4SLinus Torvalds }
725*1da177e4SLinus Torvalds 
726*1da177e4SLinus Torvalds static int class_attr_add(struct class_device *classdev,
727*1da177e4SLinus Torvalds 		struct class_device_attribute *attr)
728*1da177e4SLinus Torvalds {
729*1da177e4SLinus Torvalds 	struct class_device_attribute *base_attr;
730*1da177e4SLinus Torvalds 
731*1da177e4SLinus Torvalds 	/*
732*1da177e4SLinus Torvalds 	 * Spare the caller from having to copy things it's not interested in.
733*1da177e4SLinus Torvalds 	 */
734*1da177e4SLinus Torvalds 	base_attr = class_attr_overridden(scsi_sysfs_shost_attrs, attr);
735*1da177e4SLinus Torvalds 	if (base_attr) {
736*1da177e4SLinus Torvalds 		/* extend permissions */
737*1da177e4SLinus Torvalds 		attr->attr.mode |= base_attr->attr.mode;
738*1da177e4SLinus Torvalds 
739*1da177e4SLinus Torvalds 		/* override null show/store with default */
740*1da177e4SLinus Torvalds 		if (!attr->show)
741*1da177e4SLinus Torvalds 			attr->show = base_attr->show;
742*1da177e4SLinus Torvalds 		if (!attr->store)
743*1da177e4SLinus Torvalds 			attr->store = base_attr->store;
744*1da177e4SLinus Torvalds 	}
745*1da177e4SLinus Torvalds 
746*1da177e4SLinus Torvalds 	return class_device_create_file(classdev, attr);
747*1da177e4SLinus Torvalds }
748*1da177e4SLinus Torvalds 
749*1da177e4SLinus Torvalds /**
750*1da177e4SLinus Torvalds  * scsi_sysfs_add_host - add scsi host to subsystem
751*1da177e4SLinus Torvalds  * @shost:     scsi host struct to add to subsystem
752*1da177e4SLinus Torvalds  * @dev:       parent struct device pointer
753*1da177e4SLinus Torvalds  **/
754*1da177e4SLinus Torvalds int scsi_sysfs_add_host(struct Scsi_Host *shost)
755*1da177e4SLinus Torvalds {
756*1da177e4SLinus Torvalds 	int error, i;
757*1da177e4SLinus Torvalds 
758*1da177e4SLinus Torvalds 	if (shost->hostt->shost_attrs) {
759*1da177e4SLinus Torvalds 		for (i = 0; shost->hostt->shost_attrs[i]; i++) {
760*1da177e4SLinus Torvalds 			error = class_attr_add(&shost->shost_classdev,
761*1da177e4SLinus Torvalds 					shost->hostt->shost_attrs[i]);
762*1da177e4SLinus Torvalds 			if (error)
763*1da177e4SLinus Torvalds 				return error;
764*1da177e4SLinus Torvalds 		}
765*1da177e4SLinus Torvalds 	}
766*1da177e4SLinus Torvalds 
767*1da177e4SLinus Torvalds 	for (i = 0; scsi_sysfs_shost_attrs[i]; i++) {
768*1da177e4SLinus Torvalds 		if (!class_attr_overridden(shost->hostt->shost_attrs,
769*1da177e4SLinus Torvalds 					scsi_sysfs_shost_attrs[i])) {
770*1da177e4SLinus Torvalds 			error = class_device_create_file(&shost->shost_classdev,
771*1da177e4SLinus Torvalds 					scsi_sysfs_shost_attrs[i]);
772*1da177e4SLinus Torvalds 			if (error)
773*1da177e4SLinus Torvalds 				return error;
774*1da177e4SLinus Torvalds 		}
775*1da177e4SLinus Torvalds 	}
776*1da177e4SLinus Torvalds 
777*1da177e4SLinus Torvalds 	transport_register_device(&shost->shost_gendev);
778*1da177e4SLinus Torvalds 	return 0;
779*1da177e4SLinus Torvalds }
780*1da177e4SLinus Torvalds 
781*1da177e4SLinus Torvalds void scsi_sysfs_device_initialize(struct scsi_device *sdev)
782*1da177e4SLinus Torvalds {
783*1da177e4SLinus Torvalds 	unsigned long flags;
784*1da177e4SLinus Torvalds 	struct Scsi_Host *shost = sdev->host;
785*1da177e4SLinus Torvalds 	struct scsi_target  *starget = sdev->sdev_target;
786*1da177e4SLinus Torvalds 
787*1da177e4SLinus Torvalds 	device_initialize(&sdev->sdev_gendev);
788*1da177e4SLinus Torvalds 	sdev->sdev_gendev.bus = &scsi_bus_type;
789*1da177e4SLinus Torvalds 	sdev->sdev_gendev.release = scsi_device_dev_release;
790*1da177e4SLinus Torvalds 	sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
791*1da177e4SLinus Torvalds 		sdev->host->host_no, sdev->channel, sdev->id,
792*1da177e4SLinus Torvalds 		sdev->lun);
793*1da177e4SLinus Torvalds 
794*1da177e4SLinus Torvalds 	class_device_initialize(&sdev->sdev_classdev);
795*1da177e4SLinus Torvalds 	sdev->sdev_classdev.dev = &sdev->sdev_gendev;
796*1da177e4SLinus Torvalds 	sdev->sdev_classdev.class = &sdev_class;
797*1da177e4SLinus Torvalds 	snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
798*1da177e4SLinus Torvalds 		 "%d:%d:%d:%d", sdev->host->host_no,
799*1da177e4SLinus Torvalds 		 sdev->channel, sdev->id, sdev->lun);
800*1da177e4SLinus Torvalds 	sdev->scsi_level = SCSI_2;
801*1da177e4SLinus Torvalds 	transport_setup_device(&sdev->sdev_gendev);
802*1da177e4SLinus Torvalds 	spin_lock_irqsave(shost->host_lock, flags);
803*1da177e4SLinus Torvalds 	list_add_tail(&sdev->same_target_siblings, &starget->devices);
804*1da177e4SLinus Torvalds 	list_add_tail(&sdev->siblings, &shost->__devices);
805*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(shost->host_lock, flags);
806*1da177e4SLinus Torvalds }
807*1da177e4SLinus Torvalds 
808*1da177e4SLinus Torvalds int scsi_is_sdev_device(const struct device *dev)
809*1da177e4SLinus Torvalds {
810*1da177e4SLinus Torvalds 	return dev->release == scsi_device_dev_release;
811*1da177e4SLinus Torvalds }
812*1da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_is_sdev_device);
813*1da177e4SLinus Torvalds 
814*1da177e4SLinus Torvalds /* A blank transport template that is used in drivers that don't
815*1da177e4SLinus Torvalds  * yet implement Transport Attributes */
816*1da177e4SLinus Torvalds struct scsi_transport_template blank_transport_template = { { { {NULL, }, }, }, };
817