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