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