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
29struct kmem_cache *dasd_page_cache;
30EXPORT_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 */
42struct 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 */
56struct 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
65static 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
81int dasd_probeonly =  0;	/* is true, when probeonly mode is active */
82int dasd_autodetect = 0;	/* is true, when autodetection is active */
83int dasd_nopav = 0;		/* is true, when PAV is disabled */
84EXPORT_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 */
91static char *dasd[256];
92module_param_array(dasd, charp, NULL, 0);
93
94/*
95 * Single spinlock to protect devmap and servermap structures and lists.
96 */
97static DEFINE_SPINLOCK(dasd_devmap_lock);
98
99/*
100 * Hash lists for devmap structures.
101 */
102static struct list_head dasd_hashlists[256];
103int dasd_max_devindex;
104
105static struct dasd_devmap *dasd_add_busid(char *, int);
106
107static inline int
108dasd_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 */
124static int __init
125dasd_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 */
142static int
143dasd_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 */
202static int
203dasd_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 */
253static char *
254dasd_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, 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 */
313static char *
314dasd_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
361static char *
362dasd_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 */
379int
380dasd_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 */
412static struct dasd_devmap *
413dasd_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 */
448static struct dasd_devmap *
449dasd_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 */
470int
471dasd_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 */
480static void
481dasd_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 */
500struct dasd_device *
501dasd_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 */
529static struct dasd_devmap *
530dasd_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 */
544struct dasd_device *
545dasd_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 */
589static DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);
590
591/*
592 * Remove a dasd device structure. The passed referenced
593 * is destroyed.
594 */
595void
596dasd_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 */
643void
644dasd_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 */
654struct dasd_device *
655dasd_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 */
668struct dasd_device *
669dasd_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 */
687static ssize_t
688dasd_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
701static ssize_t
702dasd_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
730static 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 */
735static ssize_t
736dasd_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
749static ssize_t
750dasd_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
776static 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 */
782static ssize_t
783dasd_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
796static ssize_t
797dasd_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
827static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
828
829static ssize_t
830dasd_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
846static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
847
848static ssize_t
849dasd_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
886static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL);
887
888static ssize_t
889dasd_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
905static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
906
907static ssize_t
908dasd_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
924static 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
929static ssize_t
930dasd_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
948static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
949
950/*
951 * extended error-reporting
952 */
953static ssize_t
954dasd_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
967static ssize_t
968dasd_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
994static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
995
996static 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
1009static struct attribute_group dasd_attr_group = {
1010	.attrs = dasd_attrs,
1011};
1012
1013/*
1014 * Return copy of the device unique identifier.
1015 */
1016int
1017dasd_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 */
1039int
1040dasd_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}
1077EXPORT_SYMBOL_GPL(dasd_set_uid);
1078
1079/*
1080 * Return value of the specified feature.
1081 */
1082int
1083dasd_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 */
1098int
1099dasd_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
1119int
1120dasd_add_sysfs_files(struct ccw_device *cdev)
1121{
1122	return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
1123}
1124
1125void
1126dasd_remove_sysfs_files(struct ccw_device *cdev)
1127{
1128	sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
1129}
1130
1131
1132int
1133dasd_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
1147void
1148dasd_devmap_exit(void)
1149{
1150	dasd_forget_ranges();
1151}
1152