xref: /openbmc/linux/drivers/s390/block/dasd_devmap.c (revision c21b37f6)
1 /*
2  * File...........: linux/drivers/s390/block/dasd_devmap.c
3  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
4  *		    Horst Hummel <Horst.Hummel@de.ibm.com>
5  *		    Carsten Otte <Cotte@de.ibm.com>
6  *		    Martin Schwidefsky <schwidefsky@de.ibm.com>
7  * Bugreports.to..: <Linux390@de.ibm.com>
8  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
9  *
10  * Device mapping and dasd= parameter parsing functions. All devmap
11  * functions may not be called from interrupt context. In particular
12  * dasd_get_device is a no-no from interrupt context.
13  *
14  */
15 
16 #include <linux/ctype.h>
17 #include <linux/init.h>
18 #include <linux/module.h>
19 
20 #include <asm/debug.h>
21 #include <asm/uaccess.h>
22 #include <asm/ipl.h>
23 
24 /* This is ugly... */
25 #define PRINTK_HEADER "dasd_devmap:"
26 
27 #include "dasd_int.h"
28 
29 struct kmem_cache *dasd_page_cache;
30 EXPORT_SYMBOL_GPL(dasd_page_cache);
31 
32 /*
33  * dasd_devmap_t is used to store the features and the relation
34  * between device number and device index. To find a dasd_devmap_t
35  * that corresponds to a device number of a device index each
36  * dasd_devmap_t is added to two linked lists, one to search by
37  * the device number and one to search by the device index. As
38  * soon as big minor numbers are available the device index list
39  * can be removed since the device number will then be identical
40  * to the device index.
41  */
42 struct dasd_devmap {
43 	struct list_head list;
44 	char bus_id[BUS_ID_SIZE];
45         unsigned int devindex;
46         unsigned short features;
47 	struct dasd_device *device;
48 	struct dasd_uid uid;
49 };
50 
51 /*
52  * dasd_server_ssid_map contains a globally unique storage server subsystem ID.
53  * dasd_server_ssid_list contains the list of all subsystem IDs accessed by
54  * the DASD device driver.
55  */
56 struct dasd_server_ssid_map {
57 	struct list_head list;
58 	struct system_id {
59 		char vendor[4];
60 		char serial[15];
61 		__u16 ssid;
62 	} sid;
63 };
64 
65 static struct list_head dasd_server_ssid_list;
66 
67 /*
68  * Parameter parsing functions for dasd= parameter. The syntax is:
69  *   <devno>		: (0x)?[0-9a-fA-F]+
70  *   <busid>		: [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+
71  *   <feature>		: ro
72  *   <feature_list>	: \(<feature>(:<feature>)*\)
73  *   <devno-range>	: <devno>(-<devno>)?<feature_list>?
74  *   <busid-range>	: <busid>(-<busid>)?<feature_list>?
75  *   <devices>		: <devno-range>|<busid-range>
76  *   <dasd_module>	: dasd_diag_mod|dasd_eckd_mod|dasd_fba_mod
77  *
78  *   <dasd>		: autodetect|probeonly|<devices>(,<devices>)*
79  */
80 
81 int dasd_probeonly =  0;	/* is true, when probeonly mode is active */
82 int dasd_autodetect = 0;	/* is true, when autodetection is active */
83 int dasd_nopav = 0;		/* is true, when PAV is disabled */
84 EXPORT_SYMBOL_GPL(dasd_nopav);
85 
86 /*
87  * char *dasd[] is intended to hold the ranges supplied by the dasd= statement
88  * it is named 'dasd' to directly be filled by insmod with the comma separated
89  * strings when running as a module.
90  */
91 static char *dasd[256];
92 module_param_array(dasd, charp, NULL, 0);
93 
94 /*
95  * Single spinlock to protect devmap and servermap structures and lists.
96  */
97 static DEFINE_SPINLOCK(dasd_devmap_lock);
98 
99 /*
100  * Hash lists for devmap structures.
101  */
102 static struct list_head dasd_hashlists[256];
103 int dasd_max_devindex;
104 
105 static struct dasd_devmap *dasd_add_busid(char *, int);
106 
107 static inline int
108 dasd_hash_busid(char *bus_id)
109 {
110 	int hash, i;
111 
112 	hash = 0;
113 	for (i = 0; (i < BUS_ID_SIZE) && *bus_id; i++, bus_id++)
114 		hash += *bus_id;
115 	return hash & 0xff;
116 }
117 
118 #ifndef MODULE
119 /*
120  * The parameter parsing functions for builtin-drivers are called
121  * before kmalloc works. Store the pointers to the parameters strings
122  * into dasd[] for later processing.
123  */
124 static int __init
125 dasd_call_setup(char *str)
126 {
127 	static int count = 0;
128 
129 	if (count < 256)
130 		dasd[count++] = str;
131 	return 1;
132 }
133 
134 __setup ("dasd=", dasd_call_setup);
135 #endif	/* #ifndef MODULE */
136 
137 #define	DASD_IPLDEV	"ipldev"
138 
139 /*
140  * Read a device busid/devno from a string.
141  */
142 static int
143 dasd_busid(char **str, int *id0, int *id1, int *devno)
144 {
145 	int val, old_style;
146 
147 	/* Interpret ipldev busid */
148 	if (strncmp(DASD_IPLDEV, *str, strlen(DASD_IPLDEV)) == 0) {
149 		if (ipl_info.type != IPL_TYPE_CCW) {
150 			MESSAGE(KERN_ERR, "%s", "ipl device is not a ccw "
151 				"device");
152 			return -EINVAL;
153 		}
154 		*id0 = 0;
155 		*id1 = ipl_info.data.ccw.dev_id.ssid;
156 		*devno = ipl_info.data.ccw.dev_id.devno;
157 		*str += strlen(DASD_IPLDEV);
158 
159 		return 0;
160 	}
161 	/* check for leading '0x' */
162 	old_style = 0;
163 	if ((*str)[0] == '0' && (*str)[1] == 'x') {
164 		*str += 2;
165 		old_style = 1;
166 	}
167 	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
168 		return -EINVAL;
169 	val = simple_strtoul(*str, str, 16);
170 	if (old_style || (*str)[0] != '.') {
171 		*id0 = *id1 = 0;
172 		if (val < 0 || val > 0xffff)
173 			return -EINVAL;
174 		*devno = val;
175 		return 0;
176 	}
177 	/* New style x.y.z busid */
178 	if (val < 0 || val > 0xff)
179 		return -EINVAL;
180 	*id0 = val;
181 	(*str)++;
182 	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
183 		return -EINVAL;
184 	val = simple_strtoul(*str, str, 16);
185 	if (val < 0 || val > 0xff || (*str)++[0] != '.')
186 		return -EINVAL;
187 	*id1 = val;
188 	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
189 		return -EINVAL;
190 	val = simple_strtoul(*str, str, 16);
191 	if (val < 0 || val > 0xffff)
192 		return -EINVAL;
193 	*devno = val;
194 	return 0;
195 }
196 
197 /*
198  * Read colon separated list of dasd features. Currently there is
199  * only one: "ro" for read-only devices. The default feature set
200  * is empty (value 0).
201  */
202 static int
203 dasd_feature_list(char *str, char **endp)
204 {
205 	int features, len, rc;
206 
207 	rc = 0;
208 	if (*str != '(') {
209 		*endp = str;
210 		return DASD_FEATURE_DEFAULT;
211 	}
212 	str++;
213 	features = 0;
214 
215 	while (1) {
216 		for (len = 0;
217 		     str[len] && str[len] != ':' && str[len] != ')'; len++);
218 		if (len == 2 && !strncmp(str, "ro", 2))
219 			features |= DASD_FEATURE_READONLY;
220 		else if (len == 4 && !strncmp(str, "diag", 4))
221 			features |= DASD_FEATURE_USEDIAG;
222 		else if (len == 6 && !strncmp(str, "erplog", 6))
223 			features |= DASD_FEATURE_ERPLOG;
224 		else {
225 			MESSAGE(KERN_WARNING,
226 				"unsupported feature: %*s, "
227 				"ignoring setting", len, str);
228 			rc = -EINVAL;
229 		}
230 		str += len;
231 		if (*str != ':')
232 			break;
233 		str++;
234 	}
235 	if (*str != ')') {
236 		MESSAGE(KERN_WARNING, "%s",
237 			"missing ')' in dasd parameter string\n");
238 		rc = -EINVAL;
239 	} else
240 		str++;
241 	*endp = str;
242 	if (rc != 0)
243 		return rc;
244 	return features;
245 }
246 
247 /*
248  * Try to match the first element on the comma separated parse string
249  * with one of the known keywords. If a keyword is found, take the approprate
250  * action and return a pointer to the residual string. If the first element
251  * could not be matched to any keyword then return an error code.
252  */
253 static char *
254 dasd_parse_keyword( char *parsestring ) {
255 
256 	char *nextcomma, *residual_str;
257 	int length;
258 
259 	nextcomma = strchr(parsestring,',');
260 	if (nextcomma) {
261 		length = nextcomma - parsestring;
262 		residual_str = nextcomma + 1;
263 	} else {
264 		length = strlen(parsestring);
265 		residual_str = parsestring + length;
266         }
267 	if (strncmp("autodetect", parsestring, length) == 0) {
268 		dasd_autodetect = 1;
269 		MESSAGE (KERN_INFO, "%s",
270 			 "turning to autodetection mode");
271                 return residual_str;
272         }
273 	if (strncmp("probeonly", parsestring, length) == 0) {
274 		dasd_probeonly = 1;
275 		MESSAGE(KERN_INFO, "%s",
276 			"turning to probeonly mode");
277                 return residual_str;
278         }
279 	if (strncmp("nopav", parsestring, length) == 0) {
280 		if (MACHINE_IS_VM)
281 			MESSAGE(KERN_INFO, "%s", "'nopav' not supported on VM");
282 		else {
283 			dasd_nopav = 1;
284 			MESSAGE(KERN_INFO, "%s", "disable PAV mode");
285 		}
286 		return residual_str;
287 	}
288 	if (strncmp("fixedbuffers", parsestring, length) == 0) {
289 		if (dasd_page_cache)
290 			return residual_str;
291 		dasd_page_cache =
292 			kmem_cache_create("dasd_page_cache", PAGE_SIZE,
293 					  PAGE_SIZE, SLAB_CACHE_DMA,
294 					  NULL);
295 		if (!dasd_page_cache)
296 			MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
297 				"fixed buffer mode disabled.");
298 		else
299 			MESSAGE (KERN_INFO, "%s",
300 				 "turning on fixed buffer mode");
301                 return residual_str;
302         }
303 	return ERR_PTR(-EINVAL);
304 }
305 
306 /*
307  * Try to interprete the first element on the comma separated parse string
308  * as a device number or a range of devices. If the interpretation is
309  * successfull, create the matching dasd_devmap entries and return a pointer
310  * to the residual string.
311  * If interpretation fails or in case of an error, return an error code.
312  */
313 static char *
314 dasd_parse_range( char *parsestring ) {
315 
316 	struct dasd_devmap *devmap;
317 	int from, from_id0, from_id1;
318 	int to, to_id0, to_id1;
319 	int features, rc;
320 	char bus_id[BUS_ID_SIZE+1], *str;
321 
322 	str = parsestring;
323 	rc = dasd_busid(&str, &from_id0, &from_id1, &from);
324 	if (rc == 0) {
325 		to = from;
326 		to_id0 = from_id0;
327 		to_id1 = from_id1;
328 		if (*str == '-') {
329 			str++;
330 			rc = dasd_busid(&str, &to_id0, &to_id1, &to);
331 		}
332 	}
333 	if (rc == 0 &&
334 	    (from_id0 != to_id0 || from_id1 != to_id1 || from > to))
335 		rc = -EINVAL;
336 	if (rc) {
337 		MESSAGE(KERN_ERR, "Invalid device range %s", parsestring);
338 		return ERR_PTR(rc);
339 	}
340 	features = dasd_feature_list(str, &str);
341 	if (features < 0)
342 		return ERR_PTR(-EINVAL);
343 	/* each device in dasd= parameter should be set initially online */
344 	features |= DASD_FEATURE_INITIAL_ONLINE;
345 	while (from <= to) {
346 		sprintf(bus_id, "%01x.%01x.%04x",
347 			from_id0, from_id1, from++);
348 		devmap = dasd_add_busid(bus_id, features);
349 		if (IS_ERR(devmap))
350 			return (char *)devmap;
351 	}
352 	if (*str == ',')
353 		return str + 1;
354 	if (*str == '\0')
355 		return str;
356 	MESSAGE(KERN_WARNING,
357 		"junk at end of dasd parameter string: %s\n", str);
358 	return ERR_PTR(-EINVAL);
359 }
360 
361 static char *
362 dasd_parse_next_element( char *parsestring ) {
363 	char * residual_str;
364 	residual_str = dasd_parse_keyword(parsestring);
365 	if (!IS_ERR(residual_str))
366 		return residual_str;
367 	residual_str = dasd_parse_range(parsestring);
368 	return residual_str;
369 }
370 
371 /*
372  * Parse parameters stored in dasd[]
373  * The 'dasd=...' parameter allows to specify a comma separated list of
374  * keywords and device ranges. When the dasd driver is build into the kernel,
375  * the complete list will be stored as one element of the dasd[] array.
376  * When the dasd driver is build as a module, then the list is broken into
377  * it's elements and each dasd[] entry contains one element.
378  */
379 int
380 dasd_parse(void)
381 {
382 	int rc, i;
383 	char *parsestring;
384 
385 	rc = 0;
386 	for (i = 0; i < 256; i++) {
387 		if (dasd[i] == NULL)
388 			break;
389 		parsestring = dasd[i];
390 		/* loop over the comma separated list in the parsestring */
391 		while (*parsestring) {
392 			parsestring = dasd_parse_next_element(parsestring);
393 			if(IS_ERR(parsestring)) {
394 				rc = PTR_ERR(parsestring);
395 				break;
396 			}
397 		}
398 		if (rc) {
399 			DBF_EVENT(DBF_ALERT, "%s", "invalid range found");
400 			break;
401 		}
402 	}
403 	return rc;
404 }
405 
406 /*
407  * Add a devmap for the device specified by busid. It is possible that
408  * the devmap already exists (dasd= parameter). The order of the devices
409  * added through this function will define the kdevs for the individual
410  * devices.
411  */
412 static struct dasd_devmap *
413 dasd_add_busid(char *bus_id, int features)
414 {
415 	struct dasd_devmap *devmap, *new, *tmp;
416 	int hash;
417 
418 	new = (struct dasd_devmap *)
419 		kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
420 	if (!new)
421 		return ERR_PTR(-ENOMEM);
422 	spin_lock(&dasd_devmap_lock);
423 	devmap = NULL;
424 	hash = dasd_hash_busid(bus_id);
425 	list_for_each_entry(tmp, &dasd_hashlists[hash], list)
426 		if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
427 			devmap = tmp;
428 			break;
429 		}
430 	if (!devmap) {
431 		/* This bus_id is new. */
432 		new->devindex = dasd_max_devindex++;
433 		strncpy(new->bus_id, bus_id, BUS_ID_SIZE);
434 		new->features = features;
435 		new->device = NULL;
436 		list_add(&new->list, &dasd_hashlists[hash]);
437 		devmap = new;
438 		new = NULL;
439 	}
440 	spin_unlock(&dasd_devmap_lock);
441 	kfree(new);
442 	return devmap;
443 }
444 
445 /*
446  * Find devmap for device with given bus_id.
447  */
448 static struct dasd_devmap *
449 dasd_find_busid(char *bus_id)
450 {
451 	struct dasd_devmap *devmap, *tmp;
452 	int hash;
453 
454 	spin_lock(&dasd_devmap_lock);
455 	devmap = ERR_PTR(-ENODEV);
456 	hash = dasd_hash_busid(bus_id);
457 	list_for_each_entry(tmp, &dasd_hashlists[hash], list) {
458 		if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
459 			devmap = tmp;
460 			break;
461 		}
462 	}
463 	spin_unlock(&dasd_devmap_lock);
464 	return devmap;
465 }
466 
467 /*
468  * Check if busid has been added to the list of dasd ranges.
469  */
470 int
471 dasd_busid_known(char *bus_id)
472 {
473 	return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0;
474 }
475 
476 /*
477  * Forget all about the device numbers added so far.
478  * This may only be called at module unload or system shutdown.
479  */
480 static void
481 dasd_forget_ranges(void)
482 {
483 	struct dasd_devmap *devmap, *n;
484 	int i;
485 
486 	spin_lock(&dasd_devmap_lock);
487 	for (i = 0; i < 256; i++) {
488 		list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) {
489 			BUG_ON(devmap->device != NULL);
490 			list_del(&devmap->list);
491 			kfree(devmap);
492 		}
493 	}
494 	spin_unlock(&dasd_devmap_lock);
495 }
496 
497 /*
498  * Find the device struct by its device index.
499  */
500 struct dasd_device *
501 dasd_device_from_devindex(int devindex)
502 {
503 	struct dasd_devmap *devmap, *tmp;
504 	struct dasd_device *device;
505 	int i;
506 
507 	spin_lock(&dasd_devmap_lock);
508 	devmap = NULL;
509 	for (i = 0; (i < 256) && !devmap; i++)
510 		list_for_each_entry(tmp, &dasd_hashlists[i], list)
511 			if (tmp->devindex == devindex) {
512 				/* Found the devmap for the device. */
513 				devmap = tmp;
514 				break;
515 			}
516 	if (devmap && devmap->device) {
517 		device = devmap->device;
518 		dasd_get_device(device);
519 	} else
520 		device = ERR_PTR(-ENODEV);
521 	spin_unlock(&dasd_devmap_lock);
522 	return device;
523 }
524 
525 /*
526  * Return devmap for cdev. If no devmap exists yet, create one and
527  * connect it to the cdev.
528  */
529 static struct dasd_devmap *
530 dasd_devmap_from_cdev(struct ccw_device *cdev)
531 {
532 	struct dasd_devmap *devmap;
533 
534 	devmap = dasd_find_busid(cdev->dev.bus_id);
535 	if (IS_ERR(devmap))
536 		devmap = dasd_add_busid(cdev->dev.bus_id,
537 					DASD_FEATURE_DEFAULT);
538 	return devmap;
539 }
540 
541 /*
542  * Create a dasd device structure for cdev.
543  */
544 struct dasd_device *
545 dasd_create_device(struct ccw_device *cdev)
546 {
547 	struct dasd_devmap *devmap;
548 	struct dasd_device *device;
549 	unsigned long flags;
550 	int rc;
551 
552 	devmap = dasd_devmap_from_cdev(cdev);
553 	if (IS_ERR(devmap))
554 		return (void *) devmap;
555 
556 	device = dasd_alloc_device();
557 	if (IS_ERR(device))
558 		return device;
559 	atomic_set(&device->ref_count, 3);
560 
561 	spin_lock(&dasd_devmap_lock);
562 	if (!devmap->device) {
563 		devmap->device = device;
564 		device->devindex = devmap->devindex;
565 		device->features = devmap->features;
566 		get_device(&cdev->dev);
567 		device->cdev = cdev;
568 		rc = 0;
569 	} else
570 		/* Someone else was faster. */
571 		rc = -EBUSY;
572 	spin_unlock(&dasd_devmap_lock);
573 
574 	if (rc) {
575 		dasd_free_device(device);
576 		return ERR_PTR(rc);
577 	}
578 
579 	spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
580 	cdev->dev.driver_data = device;
581 	spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
582 
583 	return device;
584 }
585 
586 /*
587  * Wait queue for dasd_delete_device waits.
588  */
589 static DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);
590 
591 /*
592  * Remove a dasd device structure. The passed referenced
593  * is destroyed.
594  */
595 void
596 dasd_delete_device(struct dasd_device *device)
597 {
598 	struct ccw_device *cdev;
599 	struct dasd_devmap *devmap;
600 	unsigned long flags;
601 
602 	/* First remove device pointer from devmap. */
603 	devmap = dasd_find_busid(device->cdev->dev.bus_id);
604 	BUG_ON(IS_ERR(devmap));
605 	spin_lock(&dasd_devmap_lock);
606 	if (devmap->device != device) {
607 		spin_unlock(&dasd_devmap_lock);
608 		dasd_put_device(device);
609 		return;
610 	}
611 	devmap->device = NULL;
612 	spin_unlock(&dasd_devmap_lock);
613 
614 	/* Disconnect dasd_device structure from ccw_device structure. */
615 	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
616 	device->cdev->dev.driver_data = NULL;
617 	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
618 
619 	/*
620 	 * Drop ref_count by 3, one for the devmap reference, one for
621 	 * the cdev reference and one for the passed reference.
622 	 */
623 	atomic_sub(3, &device->ref_count);
624 
625 	/* Wait for reference counter to drop to zero. */
626 	wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);
627 
628 	/* Disconnect dasd_device structure from ccw_device structure. */
629 	cdev = device->cdev;
630 	device->cdev = NULL;
631 
632 	/* Put ccw_device structure. */
633 	put_device(&cdev->dev);
634 
635 	/* Now the device structure can be freed. */
636 	dasd_free_device(device);
637 }
638 
639 /*
640  * Reference counter dropped to zero. Wake up waiter
641  * in dasd_delete_device.
642  */
643 void
644 dasd_put_device_wake(struct dasd_device *device)
645 {
646 	wake_up(&dasd_delete_wq);
647 }
648 
649 /*
650  * Return dasd_device structure associated with cdev.
651  * This function needs to be called with the ccw device
652  * lock held. It can be used from interrupt context.
653  */
654 struct dasd_device *
655 dasd_device_from_cdev_locked(struct ccw_device *cdev)
656 {
657 	struct dasd_device *device = cdev->dev.driver_data;
658 
659 	if (!device)
660 		return ERR_PTR(-ENODEV);
661 	dasd_get_device(device);
662 	return device;
663 }
664 
665 /*
666  * Return dasd_device structure associated with cdev.
667  */
668 struct dasd_device *
669 dasd_device_from_cdev(struct ccw_device *cdev)
670 {
671 	struct dasd_device *device;
672 	unsigned long flags;
673 
674 	spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
675 	device = dasd_device_from_cdev_locked(cdev);
676 	spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
677 	return device;
678 }
679 
680 /*
681  * SECTION: files in sysfs
682  */
683 
684 /*
685  * readonly controls the readonly status of a dasd
686  */
687 static ssize_t
688 dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
689 {
690 	struct dasd_devmap *devmap;
691 	int ro_flag;
692 
693 	devmap = dasd_find_busid(dev->bus_id);
694 	if (!IS_ERR(devmap))
695 		ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
696 	else
697 		ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0;
698 	return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");
699 }
700 
701 static ssize_t
702 dasd_ro_store(struct device *dev, struct device_attribute *attr,
703 	      const char *buf, size_t count)
704 {
705 	struct dasd_devmap *devmap;
706 	int val;
707 	char *endp;
708 
709 	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
710 	if (IS_ERR(devmap))
711 		return PTR_ERR(devmap);
712 
713 	val = simple_strtoul(buf, &endp, 0);
714 	if (((endp + 1) < (buf + count)) || (val > 1))
715 		return -EINVAL;
716 
717 	spin_lock(&dasd_devmap_lock);
718 	if (val)
719 		devmap->features |= DASD_FEATURE_READONLY;
720 	else
721 		devmap->features &= ~DASD_FEATURE_READONLY;
722 	if (devmap->device)
723 		devmap->device->features = devmap->features;
724 	if (devmap->device && devmap->device->gdp)
725 		set_disk_ro(devmap->device->gdp, val);
726 	spin_unlock(&dasd_devmap_lock);
727 	return count;
728 }
729 
730 static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
731 /*
732  * erplog controls the logging of ERP related data
733  * (e.g. failing channel programs).
734  */
735 static ssize_t
736 dasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
737 {
738 	struct dasd_devmap *devmap;
739 	int erplog;
740 
741 	devmap = dasd_find_busid(dev->bus_id);
742 	if (!IS_ERR(devmap))
743 		erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
744 	else
745 		erplog = (DASD_FEATURE_DEFAULT & DASD_FEATURE_ERPLOG) != 0;
746 	return snprintf(buf, PAGE_SIZE, erplog ? "1\n" : "0\n");
747 }
748 
749 static ssize_t
750 dasd_erplog_store(struct device *dev, struct device_attribute *attr,
751 	      const char *buf, size_t count)
752 {
753 	struct dasd_devmap *devmap;
754 	int val;
755 	char *endp;
756 
757 	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
758 	if (IS_ERR(devmap))
759 		return PTR_ERR(devmap);
760 
761 	val = simple_strtoul(buf, &endp, 0);
762 	if (((endp + 1) < (buf + count)) || (val > 1))
763 		return -EINVAL;
764 
765 	spin_lock(&dasd_devmap_lock);
766 	if (val)
767 		devmap->features |= DASD_FEATURE_ERPLOG;
768 	else
769 		devmap->features &= ~DASD_FEATURE_ERPLOG;
770 	if (devmap->device)
771 		devmap->device->features = devmap->features;
772 	spin_unlock(&dasd_devmap_lock);
773 	return count;
774 }
775 
776 static DEVICE_ATTR(erplog, 0644, dasd_erplog_show, dasd_erplog_store);
777 
778 /*
779  * use_diag controls whether the driver should use diag rather than ssch
780  * to talk to the device
781  */
782 static ssize_t
783 dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
784 {
785 	struct dasd_devmap *devmap;
786 	int use_diag;
787 
788 	devmap = dasd_find_busid(dev->bus_id);
789 	if (!IS_ERR(devmap))
790 		use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
791 	else
792 		use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;
793 	return sprintf(buf, use_diag ? "1\n" : "0\n");
794 }
795 
796 static ssize_t
797 dasd_use_diag_store(struct device *dev, struct device_attribute *attr,
798 		    const char *buf, size_t count)
799 {
800 	struct dasd_devmap *devmap;
801 	ssize_t rc;
802 	int val;
803 	char *endp;
804 
805 	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
806 	if (IS_ERR(devmap))
807 		return PTR_ERR(devmap);
808 
809 	val = simple_strtoul(buf, &endp, 0);
810 	if (((endp + 1) < (buf + count)) || (val > 1))
811 		return -EINVAL;
812 
813 	spin_lock(&dasd_devmap_lock);
814 	/* Changing diag discipline flag is only allowed in offline state. */
815 	rc = count;
816 	if (!devmap->device) {
817 		if (val)
818 			devmap->features |= DASD_FEATURE_USEDIAG;
819 		else
820 			devmap->features &= ~DASD_FEATURE_USEDIAG;
821 	} else
822 		rc = -EPERM;
823 	spin_unlock(&dasd_devmap_lock);
824 	return rc;
825 }
826 
827 static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
828 
829 static ssize_t
830 dasd_discipline_show(struct device *dev, struct device_attribute *attr,
831 		     char *buf)
832 {
833 	struct dasd_device *device;
834 	ssize_t len;
835 
836 	device = dasd_device_from_cdev(to_ccwdev(dev));
837 	if (!IS_ERR(device) && device->discipline) {
838 		len = snprintf(buf, PAGE_SIZE, "%s\n",
839 			       device->discipline->name);
840 		dasd_put_device(device);
841 	} else
842 		len = snprintf(buf, PAGE_SIZE, "none\n");
843 	return len;
844 }
845 
846 static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
847 
848 static ssize_t
849 dasd_device_status_show(struct device *dev, struct device_attribute *attr,
850 		     char *buf)
851 {
852 	struct dasd_device *device;
853 	ssize_t len;
854 
855 	device = dasd_device_from_cdev(to_ccwdev(dev));
856 	if (!IS_ERR(device)) {
857 		switch (device->state) {
858 		case DASD_STATE_NEW:
859 			len = snprintf(buf, PAGE_SIZE, "new\n");
860 			break;
861 		case DASD_STATE_KNOWN:
862 			len = snprintf(buf, PAGE_SIZE, "detected\n");
863 			break;
864 		case DASD_STATE_BASIC:
865 			len = snprintf(buf, PAGE_SIZE, "basic\n");
866 			break;
867 		case DASD_STATE_UNFMT:
868 			len = snprintf(buf, PAGE_SIZE, "unformatted\n");
869 			break;
870 		case DASD_STATE_READY:
871 			len = snprintf(buf, PAGE_SIZE, "ready\n");
872 			break;
873 		case DASD_STATE_ONLINE:
874 			len = snprintf(buf, PAGE_SIZE, "online\n");
875 			break;
876 		default:
877 			len = snprintf(buf, PAGE_SIZE, "no stat\n");
878 			break;
879 		}
880 		dasd_put_device(device);
881 	} else
882 		len = snprintf(buf, PAGE_SIZE, "unknown\n");
883 	return len;
884 }
885 
886 static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL);
887 
888 static ssize_t
889 dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
890 {
891 	struct dasd_devmap *devmap;
892 	int alias;
893 
894 	devmap = dasd_find_busid(dev->bus_id);
895 	spin_lock(&dasd_devmap_lock);
896 	if (!IS_ERR(devmap))
897 		alias = devmap->uid.alias;
898 	else
899 		alias = 0;
900 	spin_unlock(&dasd_devmap_lock);
901 
902 	return sprintf(buf, alias ? "1\n" : "0\n");
903 }
904 
905 static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
906 
907 static ssize_t
908 dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
909 {
910 	struct dasd_devmap *devmap;
911 	char *vendor;
912 
913 	devmap = dasd_find_busid(dev->bus_id);
914 	spin_lock(&dasd_devmap_lock);
915 	if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
916 		vendor = devmap->uid.vendor;
917 	else
918 		vendor = "";
919 	spin_unlock(&dasd_devmap_lock);
920 
921 	return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
922 }
923 
924 static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
925 
926 #define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial    */ 14 + 1 +\
927 		     /* SSID   */ 4 + 1 + /* unit addr */ 2 + 1)
928 
929 static ssize_t
930 dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
931 {
932 	struct dasd_devmap *devmap;
933 	char uid[UID_STRLEN];
934 
935 	devmap = dasd_find_busid(dev->bus_id);
936 	spin_lock(&dasd_devmap_lock);
937 	if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
938 		snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x",
939 			 devmap->uid.vendor, devmap->uid.serial,
940 			 devmap->uid.ssid, devmap->uid.unit_addr);
941 	else
942 		uid[0] = 0;
943 	spin_unlock(&dasd_devmap_lock);
944 
945 	return snprintf(buf, PAGE_SIZE, "%s\n", uid);
946 }
947 
948 static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
949 
950 /*
951  * extended error-reporting
952  */
953 static ssize_t
954 dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
955 {
956 	struct dasd_devmap *devmap;
957 	int eer_flag;
958 
959 	devmap = dasd_find_busid(dev->bus_id);
960 	if (!IS_ERR(devmap) && devmap->device)
961 		eer_flag = dasd_eer_enabled(devmap->device);
962 	else
963 		eer_flag = 0;
964 	return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n");
965 }
966 
967 static ssize_t
968 dasd_eer_store(struct device *dev, struct device_attribute *attr,
969 	       const char *buf, size_t count)
970 {
971 	struct dasd_devmap *devmap;
972 	int val, rc;
973 	char *endp;
974 
975 	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
976 	if (IS_ERR(devmap))
977 		return PTR_ERR(devmap);
978 	if (!devmap->device)
979 		return -ENODEV;
980 
981 	val = simple_strtoul(buf, &endp, 0);
982 	if (((endp + 1) < (buf + count)) || (val > 1))
983 		return -EINVAL;
984 
985 	if (val) {
986 		rc = dasd_eer_enable(devmap->device);
987 		if (rc)
988 			return rc;
989 	} else
990 		dasd_eer_disable(devmap->device);
991 	return count;
992 }
993 
994 static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
995 
996 static struct attribute * dasd_attrs[] = {
997 	&dev_attr_readonly.attr,
998 	&dev_attr_discipline.attr,
999 	&dev_attr_status.attr,
1000 	&dev_attr_alias.attr,
1001 	&dev_attr_vendor.attr,
1002 	&dev_attr_uid.attr,
1003 	&dev_attr_use_diag.attr,
1004 	&dev_attr_eer_enabled.attr,
1005 	&dev_attr_erplog.attr,
1006 	NULL,
1007 };
1008 
1009 static struct attribute_group dasd_attr_group = {
1010 	.attrs = dasd_attrs,
1011 };
1012 
1013 /*
1014  * Return copy of the device unique identifier.
1015  */
1016 int
1017 dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
1018 {
1019 	struct dasd_devmap *devmap;
1020 
1021 	devmap = dasd_find_busid(cdev->dev.bus_id);
1022 	if (IS_ERR(devmap))
1023 		return PTR_ERR(devmap);
1024 	spin_lock(&dasd_devmap_lock);
1025 	*uid = devmap->uid;
1026 	spin_unlock(&dasd_devmap_lock);
1027 	return 0;
1028 }
1029 
1030 /*
1031  * Register the given device unique identifier into devmap struct.
1032  * In addition check if the related storage server subsystem ID is already
1033  * contained in the dasd_server_ssid_list. If subsystem ID is not contained,
1034  * create new entry.
1035  * Return 0 if server was already in serverlist,
1036  *	  1 if the server was added successful
1037  *	 <0 in case of error.
1038  */
1039 int
1040 dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
1041 {
1042 	struct dasd_devmap *devmap;
1043 	struct dasd_server_ssid_map *srv, *tmp;
1044 
1045 	devmap = dasd_find_busid(cdev->dev.bus_id);
1046 	if (IS_ERR(devmap))
1047 		return PTR_ERR(devmap);
1048 
1049 	/* generate entry for server_ssid_map */
1050 	srv = (struct dasd_server_ssid_map *)
1051 		kzalloc(sizeof(struct dasd_server_ssid_map), GFP_KERNEL);
1052 	if (!srv)
1053 		return -ENOMEM;
1054 	strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1);
1055 	strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1);
1056 	srv->sid.ssid = uid->ssid;
1057 
1058 	/* server is already contained ? */
1059 	spin_lock(&dasd_devmap_lock);
1060 	devmap->uid = *uid;
1061 	list_for_each_entry(tmp, &dasd_server_ssid_list, list) {
1062 		if (!memcmp(&srv->sid, &tmp->sid,
1063 			    sizeof(struct system_id))) {
1064 			kfree(srv);
1065 			srv = NULL;
1066 			break;
1067 		}
1068 	}
1069 
1070 	/* add servermap to serverlist */
1071 	if (srv)
1072 		list_add(&srv->list, &dasd_server_ssid_list);
1073 	spin_unlock(&dasd_devmap_lock);
1074 
1075 	return (srv ? 1 : 0);
1076 }
1077 EXPORT_SYMBOL_GPL(dasd_set_uid);
1078 
1079 /*
1080  * Return value of the specified feature.
1081  */
1082 int
1083 dasd_get_feature(struct ccw_device *cdev, int feature)
1084 {
1085 	struct dasd_devmap *devmap;
1086 
1087 	devmap = dasd_find_busid(cdev->dev.bus_id);
1088 	if (IS_ERR(devmap))
1089 		return PTR_ERR(devmap);
1090 
1091 	return ((devmap->features & feature) != 0);
1092 }
1093 
1094 /*
1095  * Set / reset given feature.
1096  * Flag indicates wether to set (!=0) or the reset (=0) the feature.
1097  */
1098 int
1099 dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
1100 {
1101 	struct dasd_devmap *devmap;
1102 
1103 	devmap = dasd_find_busid(cdev->dev.bus_id);
1104 	if (IS_ERR(devmap))
1105 		return PTR_ERR(devmap);
1106 
1107 	spin_lock(&dasd_devmap_lock);
1108 	if (flag)
1109 		devmap->features |= feature;
1110 	else
1111 		devmap->features &= ~feature;
1112 	if (devmap->device)
1113 		devmap->device->features = devmap->features;
1114 	spin_unlock(&dasd_devmap_lock);
1115 	return 0;
1116 }
1117 
1118 
1119 int
1120 dasd_add_sysfs_files(struct ccw_device *cdev)
1121 {
1122 	return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
1123 }
1124 
1125 void
1126 dasd_remove_sysfs_files(struct ccw_device *cdev)
1127 {
1128 	sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
1129 }
1130 
1131 
1132 int
1133 dasd_devmap_init(void)
1134 {
1135 	int i;
1136 
1137 	/* Initialize devmap structures. */
1138 	dasd_max_devindex = 0;
1139 	for (i = 0; i < 256; i++)
1140 		INIT_LIST_HEAD(&dasd_hashlists[i]);
1141 
1142 	/* Initialize servermap structure. */
1143 	INIT_LIST_HEAD(&dasd_server_ssid_list);
1144 	return 0;
1145 }
1146 
1147 void
1148 dasd_devmap_exit(void)
1149 {
1150 	dasd_forget_ranges();
1151 }
1152