dasd_devmap.c revision 8e09f21574ea3028d5629e5de759e0b196c690c5
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * File...........: linux/drivers/s390/block/dasd_devmap.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		    Horst Hummel <Horst.Hummel@de.ibm.com>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		    Carsten Otte <Cotte@de.ibm.com>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		    Martin Schwidefsky <schwidefsky@de.ibm.com>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bugreports.to..: <Linux390@de.ibm.com>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Device mapping and dasd= parameter parsing functions. All devmap
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * functions may not be called from interrupt context. In particular
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dasd_get_device is a no-no from interrupt context.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ctype.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
188d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russell#include <linux/module.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/debug.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
227039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter#include <asm/ipl.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is ugly... */
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PRINTK_HEADER "dasd_devmap:"
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "dasd_int.h"
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29e18b890bb0881bbab6f4f1a6cd20d9c60d66b003Christoph Lameterstruct kmem_cache *dasd_page_cache;
30405455734e1cdec09c37233216f9240cb1a058e5Horst HummelEXPORT_SYMBOL_GPL(dasd_page_cache);
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dasd_devmap_t is used to store the features and the relation
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * between device number and device index. To find a dasd_devmap_t
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that corresponds to a device number of a device index each
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dasd_devmap_t is added to two linked lists, one to search by
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the device number and one to search by the device index. As
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * soon as big minor numbers are available the device index list
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can be removed since the device number will then be identical
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the device index.
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_devmap {
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head list;
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char bus_id[BUS_ID_SIZE];
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int devindex;
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned short features;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_device *device;
483d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	struct dasd_uid uid;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Parameter parsing functions for dasd= parameter. The syntax is:
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <devno>		: (0x)?[0-9a-fA-F]+
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <busid>		: [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <feature>		: ro
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <feature_list>	: \(<feature>(:<feature>)*\)
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <devno-range>	: <devno>(-<devno>)?<feature_list>?
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <busid-range>	: <busid>(-<busid>)?<feature_list>?
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <devices>		: <devno-range>|<busid-range>
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <dasd_module>	: dasd_diag_mod|dasd_eckd_mod|dasd_fba_mod
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <dasd>		: autodetect|probeonly|<devices>(,<devices>)*
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dasd_probeonly =  0;	/* is true, when probeonly mode is active */
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dasd_autodetect = 0;	/* is true, when autodetection is active */
67405455734e1cdec09c37233216f9240cb1a058e5Horst Hummelint dasd_nopav = 0;		/* is true, when PAV is disabled */
68405455734e1cdec09c37233216f9240cb1a058e5Horst HummelEXPORT_SYMBOL_GPL(dasd_nopav);
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * char *dasd[] is intended to hold the ranges supplied by the dasd= statement
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it is named 'dasd' to directly be filled by insmod with the comma separated
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * strings when running as a module.
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *dasd[256];
768d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param_array(dasd, charp, NULL, 0);
778d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russell
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
79d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel * Single spinlock to protect devmap and servermap structures and lists.
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(dasd_devmap_lock);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Hash lists for devmap structures.
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct list_head dasd_hashlists[256];
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dasd_max_devindex;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dasd_devmap *dasd_add_busid(char *, int);
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_hash_busid(char *bus_id)
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int hash, i;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hash = 0;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; (i < BUS_ID_SIZE) && *bus_id; i++, bus_id++)
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hash += *bus_id;
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return hash & 0xff;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef MODULE
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The parameter parsing functions for builtin-drivers are called
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * before kmalloc works. Store the pointers to the parameters strings
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * into dasd[] for later processing.
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_call_setup(char *str)
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static int count = 0;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count < 256)
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd[count++] = str;
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__setup ("dasd=", dasd_call_setup);
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* #ifndef MODULE */
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1217039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter#define	DASD_IPLDEV	"ipldev"
1227039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read a device busid/devno from a string.
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1264d284cac76d0bfebc42d76b428c4e44d921200a9Heiko Carstensstatic int
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_busid(char **str, int *id0, int *id1, int *devno)
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val, old_style;
130138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel
1317039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter	/* Interpret ipldev busid */
1327039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter	if (strncmp(DASD_IPLDEV, *str, strlen(DASD_IPLDEV)) == 0) {
1337039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		if (ipl_info.type != IPL_TYPE_CCW) {
1347039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter			MESSAGE(KERN_ERR, "%s", "ipl device is not a ccw "
1357039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter				"device");
1367039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter			return -EINVAL;
1377039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		}
1387039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		*id0 = 0;
1397039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		*id1 = ipl_info.data.ccw.dev_id.ssid;
1407039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		*devno = ipl_info.data.ccw.dev_id.devno;
1417039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		*str += strlen(DASD_IPLDEV);
1427039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter
1437039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		return 0;
1447039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter	}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check for leading '0x' */
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	old_style = 0;
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((*str)[0] == '0' && (*str)[1] == 'x') {
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*str += 2;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		old_style = 1;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(*str, str, 16);
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (old_style || (*str)[0] != '.') {
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*id0 = *id1 = 0;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val < 0 || val > 0xffff)
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*devno = val;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* New style x.y.z busid */
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val < 0 || val > 0xff)
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*id0 = val;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(*str)++;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(*str, str, 16);
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val < 0 || val > 0xff || (*str)++[0] != '.')
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*id1 = val;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(*str, str, 16);
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val < 0 || val > 0xffff)
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*devno = val;
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read colon separated list of dasd features. Currently there is
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * only one: "ro" for read-only devices. The default feature set
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is empty (value 0).
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1864d284cac76d0bfebc42d76b428c4e44d921200a9Heiko Carstensstatic int
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_feature_list(char *str, char **endp)
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int features, len, rc;
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = 0;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*str != '(') {
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*endp = str;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return DASD_FEATURE_DEFAULT;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	str++;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	features = 0;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (1) {
200138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel		for (len = 0;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     str[len] && str[len] != ':' && str[len] != ')'; len++);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (len == 2 && !strncmp(str, "ro", 2))
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			features |= DASD_FEATURE_READONLY;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else if (len == 4 && !strncmp(str, "diag", 4))
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			features |= DASD_FEATURE_USEDIAG;
2069575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		else if (len == 6 && !strncmp(str, "erplog", 6))
2079575bf265711cabe7147a68003a56a9f19f034daHorst Hummel			features |= DASD_FEATURE_ERPLOG;
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MESSAGE(KERN_WARNING,
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"unsupported feature: %*s, "
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"ignoring setting", len, str);
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rc = -EINVAL;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str += len;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (*str != ':')
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str++;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*str != ')') {
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MESSAGE(KERN_WARNING, "%s",
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"missing ')' in dasd parameter string\n");
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = -EINVAL;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str++;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*endp = str;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc != 0)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return rc;
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return features;
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try to match the first element on the comma separated parse string
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with one of the known keywords. If a keyword is found, take the approprate
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * action and return a pointer to the residual string. If the first element
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * could not be matched to any keyword then return an error code.
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse_keyword( char *parsestring ) {
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *nextcomma, *residual_str;
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int length;
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nextcomma = strchr(parsestring,',');
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nextcomma) {
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		length = nextcomma - parsestring;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		residual_str = nextcomma + 1;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		length = strlen(parsestring);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		residual_str = parsestring + length;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
251405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	if (strncmp("autodetect", parsestring, length) == 0) {
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_autodetect = 1;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MESSAGE (KERN_INFO, "%s",
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 "turning to autodetection mode");
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                return residual_str;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
257405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	if (strncmp("probeonly", parsestring, length) == 0) {
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_probeonly = 1;
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MESSAGE(KERN_INFO, "%s",
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"turning to probeonly mode");
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                return residual_str;
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
263405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	if (strncmp("nopav", parsestring, length) == 0) {
264dcd707b4bdc10b4fa20efa116dbaeded21513115Peter Oberparleiter		if (MACHINE_IS_VM)
265dcd707b4bdc10b4fa20efa116dbaeded21513115Peter Oberparleiter			MESSAGE(KERN_INFO, "%s", "'nopav' not supported on VM");
266dcd707b4bdc10b4fa20efa116dbaeded21513115Peter Oberparleiter		else {
267dcd707b4bdc10b4fa20efa116dbaeded21513115Peter Oberparleiter			dasd_nopav = 1;
268dcd707b4bdc10b4fa20efa116dbaeded21513115Peter Oberparleiter			MESSAGE(KERN_INFO, "%s", "disable PAV mode");
269dcd707b4bdc10b4fa20efa116dbaeded21513115Peter Oberparleiter		}
270405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel		return residual_str;
271405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	}
272405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	if (strncmp("fixedbuffers", parsestring, length) == 0) {
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dasd_page_cache)
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return residual_str;
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_page_cache =
2762f6c55fc3109bcfa1bb1a112c825e07212c20f37Heiko Carstens			kmem_cache_create("dasd_page_cache", PAGE_SIZE,
2772f6c55fc3109bcfa1bb1a112c825e07212c20f37Heiko Carstens					  PAGE_SIZE, SLAB_CACHE_DMA,
27820c2df83d25c6a95affe6157a4c9cac4cf5ffaacPaul Mundt					  NULL);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!dasd_page_cache)
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"fixed buffer mode disabled.");
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MESSAGE (KERN_INFO, "%s",
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 "turning on fixed buffer mode");
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                return residual_str;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ERR_PTR(-EINVAL);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try to interprete the first element on the comma separated parse string
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as a device number or a range of devices. If the interpretation is
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * successfull, create the matching dasd_devmap entries and return a pointer
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the residual string.
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If interpretation fails or in case of an error, return an error code.
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse_range( char *parsestring ) {
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int from, from_id0, from_id1;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int to, to_id0, to_id1;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int features, rc;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char bus_id[BUS_ID_SIZE+1], *str;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	str = parsestring;
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = dasd_busid(&str, &from_id0, &from_id1, &from);
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc == 0) {
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to = from;
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to_id0 = from_id0;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to_id1 = from_id1;
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (*str == '-') {
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			str++;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rc = dasd_busid(&str, &to_id0, &to_id1, &to);
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc == 0 &&
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (from_id0 != to_id0 || from_id1 != to_id1 || from > to))
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = -EINVAL;
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc) {
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MESSAGE(KERN_ERR, "Invalid device range %s", parsestring);
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(rc);
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	features = dasd_feature_list(str, &str);
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (features < 0)
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(-EINVAL);
327405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	/* each device in dasd= parameter should be set initially online */
328405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	features |= DASD_FEATURE_INITIAL_ONLINE;
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (from <= to) {
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sprintf(bus_id, "%01x.%01x.%04x",
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			from_id0, from_id1, from++);
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		devmap = dasd_add_busid(bus_id, features);
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (IS_ERR(devmap))
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (char *)devmap;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*str == ',')
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return str + 1;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*str == '\0')
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return str;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MESSAGE(KERN_WARNING,
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"junk at end of dasd parameter string: %s\n", str);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ERR_PTR(-EINVAL);
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3454d284cac76d0bfebc42d76b428c4e44d921200a9Heiko Carstensstatic char *
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse_next_element( char *parsestring ) {
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char * residual_str;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	residual_str = dasd_parse_keyword(parsestring);
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!IS_ERR(residual_str))
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return residual_str;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	residual_str = dasd_parse_range(parsestring);
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return residual_str;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Parse parameters stored in dasd[]
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The 'dasd=...' parameter allows to specify a comma separated list of
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * keywords and device ranges. When the dasd driver is build into the kernel,
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the complete list will be stored as one element of the dasd[] array.
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When the dasd driver is build as a module, then the list is broken into
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it's elements and each dasd[] entry contains one element.
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse(void)
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc, i;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *parsestring;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = 0;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 256; i++) {
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dasd[i] == NULL)
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		parsestring = dasd[i];
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* loop over the comma separated list in the parsestring */
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (*parsestring) {
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			parsestring = dasd_parse_next_element(parsestring);
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if(IS_ERR(parsestring)) {
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rc = PTR_ERR(parsestring);
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc) {
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DBF_EVENT(DBF_ALERT, "%s", "invalid range found");
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Add a devmap for the device specified by busid. It is possible that
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the devmap already exists (dasd= parameter). The order of the devices
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * added through this function will define the kdevs for the individual
394138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel * devices.
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dasd_devmap *
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_add_busid(char *bus_id, int features)
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap, *new, *tmp;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int hash;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new = (struct dasd_devmap *)
403138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel		kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!new)
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(-ENOMEM);
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
407d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens	devmap = NULL;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hash = dasd_hash_busid(bus_id);
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(tmp, &dasd_hashlists[hash], list)
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			devmap = tmp;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!devmap) {
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* This bus_id is new. */
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		new->devindex = dasd_max_devindex++;
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		strncpy(new->bus_id, bus_id, BUS_ID_SIZE);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		new->features = features;
419d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens		new->device = NULL;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_add(&new->list, &dasd_hashlists[hash]);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		devmap = new;
422d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens		new = NULL;
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
42517fd682e544556a2a829e94383239c029bb21c5eJesper Juhl	kfree(new);
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return devmap;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find devmap for device with given bus_id.
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dasd_devmap *
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_find_busid(char *bus_id)
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap, *tmp;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int hash;
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = ERR_PTR(-ENODEV);
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hash = dasd_hash_busid(bus_id);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(tmp, &dasd_hashlists[hash], list) {
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			devmap = tmp;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return devmap;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check if busid has been added to the list of dasd ranges.
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_busid_known(char *bus_id)
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0;
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Forget all about the device numbers added so far.
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This may only be called at module unload or system shutdown.
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_forget_ranges(void)
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap, *n;
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 256; i++) {
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) {
473606f44228e257ea1e35557c2fec7133cca634096Eric Sesterhenn			BUG_ON(devmap->device != NULL);
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_del(&devmap->list);
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kfree(devmap);
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find the device struct by its device index.
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_device *
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_device_from_devindex(int devindex)
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap, *tmp;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_device *device;
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
492d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens	devmap = NULL;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; (i < 256) && !devmap; i++)
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_for_each_entry(tmp, &dasd_hashlists[i], list)
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tmp->devindex == devindex) {
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Found the devmap for the device. */
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				devmap = tmp;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (devmap && devmap->device) {
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		device = devmap->device;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_get_device(device);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		device = ERR_PTR(-ENODEV);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return device;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return devmap for cdev. If no devmap exists yet, create one and
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * connect it to the cdev.
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dasd_devmap *
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_devmap_from_cdev(struct ccw_device *cdev)
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = dasd_find_busid(cdev->dev.bus_id);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(devmap))
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		devmap = dasd_add_busid(cdev->dev.bus_id,
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					DASD_FEATURE_DEFAULT);
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return devmap;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Create a dasd device structure for cdev.
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_device *
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_create_device(struct ccw_device *cdev)
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_device *device;
533a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	unsigned long flags;
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = dasd_devmap_from_cdev(cdev);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(devmap))
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (void *) devmap;
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device = dasd_alloc_device();
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(device))
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return device;
543a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	atomic_set(&device->ref_count, 3);
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!devmap->device) {
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		devmap->device = device;
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		device->devindex = devmap->devindex;
549c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel		device->features = devmap->features;
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		get_device(&cdev->dev);
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		device->cdev = cdev;
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = 0;
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Someone else was faster. */
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = -EBUSY;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc) {
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_free_device(device);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(rc);
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
562a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky
563a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
564a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	cdev->dev.driver_data = device;
565a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
566a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return device;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wait queue for dasd_delete_device waits.
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Remove a dasd device structure. The passed referenced
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is destroyed.
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_delete_device(struct dasd_device *device)
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ccw_device *cdev;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
584a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	unsigned long flags;
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* First remove device pointer from devmap. */
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = dasd_find_busid(device->cdev->dev.bus_id);
588606f44228e257ea1e35557c2fec7133cca634096Eric Sesterhenn	BUG_ON(IS_ERR(devmap));
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (devmap->device != device) {
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock(&dasd_devmap_lock);
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_put_device(device);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap->device = NULL;
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
598a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	/* Disconnect dasd_device structure from ccw_device structure. */
599a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
600a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	device->cdev->dev.driver_data = NULL;
601a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
602a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky
603a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	/*
604a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	 * Drop ref_count by 3, one for the devmap reference, one for
605a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	 * the cdev reference and one for the passed reference.
606a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	 */
607a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	atomic_sub(3, &device->ref_count);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Wait for reference counter to drop to zero. */
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Disconnect dasd_device structure from ccw_device structure. */
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cdev = device->cdev;
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device->cdev = NULL;
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Put ccw_device structure. */
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_device(&cdev->dev);
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now the device structure can be freed. */
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dasd_free_device(device);
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reference counter dropped to zero. Wake up waiter
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in dasd_delete_device.
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_put_device_wake(struct dasd_device *device)
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wake_up(&dasd_delete_wq);
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return dasd_device structure associated with cdev.
635a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky * This function needs to be called with the ccw device
636a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky * lock held. It can be used from interrupt context.
637a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky */
638a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefskystruct dasd_device *
639a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefskydasd_device_from_cdev_locked(struct ccw_device *cdev)
640a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky{
641a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	struct dasd_device *device = cdev->dev.driver_data;
642a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky
643a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	if (!device)
644a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky		return ERR_PTR(-ENODEV);
645a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	dasd_get_device(device);
646a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	return device;
647a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky}
648a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky
649a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky/*
650a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky * Return dasd_device structure associated with cdev.
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_device *
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_device_from_cdev(struct ccw_device *cdev)
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_device *device;
656a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	unsigned long flags;
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
658a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
659a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	device = dasd_device_from_cdev_locked(cdev);
660a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return device;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SECTION: files in sysfs
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * readonly controls the readonly status of a dasd
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
672e404e274f62665f3333d6a539d0d3701f678a598Yani Ioannoudasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ro_flag;
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = dasd_find_busid(dev->bus_id);
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!IS_ERR(devmap))
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
686138c014dcba74211dc4e835658f34a787c40cf17Horst Hummeldasd_ro_store(struct device *dev, struct device_attribute *attr,
687138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel	      const char *buf, size_t count)
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
69001376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	int val;
69101376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	char *endp;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(devmap))
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return PTR_ERR(devmap);
69601376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
69701376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	val = simple_strtoul(buf, &endp, 0);
69801376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	if (((endp + 1) < (buf + count)) || (val > 1))
69901376f4495840f3daf6d73679242b5964fc9603bHorst Hummel		return -EINVAL;
70001376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
70201376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	if (val)
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		devmap->features |= DASD_FEATURE_READONLY;
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		devmap->features &= ~DASD_FEATURE_READONLY;
706c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel	if (devmap->device)
707c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel		devmap->device->features = devmap->features;
7088e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	if (devmap->device && devmap->device->block
7098e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	    && devmap->device->block->gdp)
7108e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		set_disk_ro(devmap->device->block->gdp, val);
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
7169575bf265711cabe7147a68003a56a9f19f034daHorst Hummel/*
7179575bf265711cabe7147a68003a56a9f19f034daHorst Hummel * erplog controls the logging of ERP related data
7189575bf265711cabe7147a68003a56a9f19f034daHorst Hummel * (e.g. failing channel programs).
7199575bf265711cabe7147a68003a56a9f19f034daHorst Hummel */
7209575bf265711cabe7147a68003a56a9f19f034daHorst Hummelstatic ssize_t
7219575bf265711cabe7147a68003a56a9f19f034daHorst Hummeldasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
7229575bf265711cabe7147a68003a56a9f19f034daHorst Hummel{
7239575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	struct dasd_devmap *devmap;
7249575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	int erplog;
7259575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
7269575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	devmap = dasd_find_busid(dev->bus_id);
7279575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	if (!IS_ERR(devmap))
7289575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
7299575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	else
7309575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		erplog = (DASD_FEATURE_DEFAULT & DASD_FEATURE_ERPLOG) != 0;
7319575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	return snprintf(buf, PAGE_SIZE, erplog ? "1\n" : "0\n");
7329575bf265711cabe7147a68003a56a9f19f034daHorst Hummel}
7339575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
7349575bf265711cabe7147a68003a56a9f19f034daHorst Hummelstatic ssize_t
7359575bf265711cabe7147a68003a56a9f19f034daHorst Hummeldasd_erplog_store(struct device *dev, struct device_attribute *attr,
7369575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	      const char *buf, size_t count)
7379575bf265711cabe7147a68003a56a9f19f034daHorst Hummel{
7389575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	struct dasd_devmap *devmap;
7399575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	int val;
7409575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	char *endp;
7419575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
7429575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
7439575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	if (IS_ERR(devmap))
7449575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		return PTR_ERR(devmap);
7459575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
7469575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	val = simple_strtoul(buf, &endp, 0);
7479575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	if (((endp + 1) < (buf + count)) || (val > 1))
7489575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		return -EINVAL;
7499575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
7509575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	spin_lock(&dasd_devmap_lock);
7519575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	if (val)
7529575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		devmap->features |= DASD_FEATURE_ERPLOG;
7539575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	else
7549575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		devmap->features &= ~DASD_FEATURE_ERPLOG;
7559575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	if (devmap->device)
7569575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		devmap->device->features = devmap->features;
7579575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	spin_unlock(&dasd_devmap_lock);
7589575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	return count;
7599575bf265711cabe7147a68003a56a9f19f034daHorst Hummel}
7609575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
7619575bf265711cabe7147a68003a56a9f19f034daHorst Hummelstatic DEVICE_ATTR(erplog, 0644, dasd_erplog_show, dasd_erplog_store);
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * use_diag controls whether the driver should use diag rather than ssch
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to talk to the device
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
767138c014dcba74211dc4e835658f34a787c40cf17Horst Hummelstatic ssize_t
768e404e274f62665f3333d6a539d0d3701f678a598Yani Ioannoudasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int use_diag;
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = dasd_find_busid(dev->bus_id);
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!IS_ERR(devmap))
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, use_diag ? "1\n" : "0\n");
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
782138c014dcba74211dc4e835658f34a787c40cf17Horst Hummeldasd_use_diag_store(struct device *dev, struct device_attribute *attr,
783138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel		    const char *buf, size_t count)
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ssize_t rc;
78701376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	int val;
78801376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	char *endp;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(devmap))
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return PTR_ERR(devmap);
79301376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
79401376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	val = simple_strtoul(buf, &endp, 0);
79501376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	if (((endp + 1) < (buf + count)) || (val > 1))
79601376f4495840f3daf6d73679242b5964fc9603bHorst Hummel		return -EINVAL;
79701376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Changing diag discipline flag is only allowed in offline state. */
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = count;
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!devmap->device) {
80201376f4495840f3daf6d73679242b5964fc9603bHorst Hummel		if (val)
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			devmap->features |= DASD_FEATURE_USEDIAG;
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			devmap->features &= ~DASD_FEATURE_USEDIAG;
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = -EPERM;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
812138c014dcba74211dc4e835658f34a787c40cf17Horst Hummelstatic DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
815138c014dcba74211dc4e835658f34a787c40cf17Horst Hummeldasd_discipline_show(struct device *dev, struct device_attribute *attr,
816138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel		     char *buf)
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
818a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	struct dasd_device *device;
819a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	ssize_t len;
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	device = dasd_device_from_cdev(to_ccwdev(dev));
822a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	if (!IS_ERR(device) && device->discipline) {
823a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky		len = snprintf(buf, PAGE_SIZE, "%s\n",
824a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky			       device->discipline->name);
825a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky		dasd_put_device(device);
826a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	} else
827a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky		len = snprintf(buf, PAGE_SIZE, "none\n");
828a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	return len;
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8333d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic ssize_t
8344dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummeldasd_device_status_show(struct device *dev, struct device_attribute *attr,
8354dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		     char *buf)
8364dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel{
8374dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	struct dasd_device *device;
8384dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	ssize_t len;
8394dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel
8404dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	device = dasd_device_from_cdev(to_ccwdev(dev));
8414dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	if (!IS_ERR(device)) {
8424dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		switch (device->state) {
8434dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_NEW:
8444dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "new\n");
8454dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
8464dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_KNOWN:
8474dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "detected\n");
8484dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
8494dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_BASIC:
8504dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "basic\n");
8514dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
8524dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_UNFMT:
8534dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "unformatted\n");
8544dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
8554dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_READY:
8564dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "ready\n");
8574dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
8584dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_ONLINE:
8594dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "online\n");
8604dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
8614dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		default:
8624dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "no stat\n");
8634dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
8644dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		}
8654dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		dasd_put_device(device);
8664dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	} else
8674dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		len = snprintf(buf, PAGE_SIZE, "unknown\n");
8684dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	return len;
8694dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel}
8704dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel
8714dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummelstatic DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL);
8724dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel
8734dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummelstatic ssize_t
8743d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummeldasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
8753d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{
8763d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	struct dasd_devmap *devmap;
8773d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	int alias;
8783d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
8793d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	devmap = dasd_find_busid(dev->bus_id);
8803d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	spin_lock(&dasd_devmap_lock);
8818e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
8828e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		spin_unlock(&dasd_devmap_lock);
8838e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		return sprintf(buf, "0\n");
8848e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	}
8858e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	if (devmap->uid.type == UA_BASE_PAV_ALIAS ||
8868e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	    devmap->uid.type == UA_HYPER_PAV_ALIAS)
8878e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		alias = 1;
8883d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	else
8893d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel		alias = 0;
8903d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	spin_unlock(&dasd_devmap_lock);
8913d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	return sprintf(buf, alias ? "1\n" : "0\n");
8923d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel}
8933d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
8943d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
8953d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
8963d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic ssize_t
8973d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummeldasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
8983d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{
8993d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	struct dasd_devmap *devmap;
9003d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	char *vendor;
9013d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
9023d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	devmap = dasd_find_busid(dev->bus_id);
9033d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	spin_lock(&dasd_devmap_lock);
9043d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
9053d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel		vendor = devmap->uid.vendor;
9063d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	else
9073d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel		vendor = "";
9083d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	spin_unlock(&dasd_devmap_lock);
9093d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
9103d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
9113d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel}
9123d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
9133d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
9143d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
9153d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel#define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial    */ 14 + 1 +\
9163d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel		     /* SSID   */ 4 + 1 + /* unit addr */ 2 + 1)
9173d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
9183d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic ssize_t
9193d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummeldasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
9203d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{
9213d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	struct dasd_devmap *devmap;
9228e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	char uid_string[UID_STRLEN];
9238e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	char ua_string[3];
9248e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	struct dasd_uid *uid;
9253d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
9263d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	devmap = dasd_find_busid(dev->bus_id);
9273d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	spin_lock(&dasd_devmap_lock);
9288e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
9298e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		spin_unlock(&dasd_devmap_lock);
9308e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		return sprintf(buf, "\n");
9318e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	}
9328e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	uid = &devmap->uid;
9338e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	switch (uid->type) {
9348e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	case UA_BASE_DEVICE:
9358e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		sprintf(ua_string, "%02x", uid->real_unit_addr);
9368e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		break;
9378e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	case UA_BASE_PAV_ALIAS:
9388e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		sprintf(ua_string, "%02x", uid->base_unit_addr);
9398e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		break;
9408e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	case UA_HYPER_PAV_ALIAS:
9418e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		sprintf(ua_string, "xx");
9428e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		break;
9438e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	default:
9448e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		/* should not happen, treat like base device */
9458e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		sprintf(ua_string, "%02x", uid->real_unit_addr);
9468e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		break;
9478e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	}
9488e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	snprintf(uid_string, sizeof(uid_string), "%s.%s.%04x.%s",
9498e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		 uid->vendor, uid->serial, uid->ssid, ua_string);
9503d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	spin_unlock(&dasd_devmap_lock);
9518e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
9523d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel}
9533d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
9543d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
9553d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
95620c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber/*
95720c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber * extended error-reporting
95820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber */
95920c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberstatic ssize_t
96020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberdasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
96120c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber{
96220c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	struct dasd_devmap *devmap;
96320c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	int eer_flag;
96420c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber
96520c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	devmap = dasd_find_busid(dev->bus_id);
96620c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	if (!IS_ERR(devmap) && devmap->device)
96720c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber		eer_flag = dasd_eer_enabled(devmap->device);
96820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	else
96920c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber		eer_flag = 0;
97020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n");
97120c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber}
97220c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber
97320c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberstatic ssize_t
97420c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberdasd_eer_store(struct device *dev, struct device_attribute *attr,
97520c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	       const char *buf, size_t count)
97620c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber{
97720c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	struct dasd_devmap *devmap;
97801376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	int val, rc;
97901376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	char *endp;
98020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber
98120c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
98220c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	if (IS_ERR(devmap))
98320c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber		return PTR_ERR(devmap);
98420c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	if (!devmap->device)
98501376f4495840f3daf6d73679242b5964fc9603bHorst Hummel		return -ENODEV;
98601376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
98701376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	val = simple_strtoul(buf, &endp, 0);
98801376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	if (((endp + 1) < (buf + count)) || (val > 1))
98901376f4495840f3daf6d73679242b5964fc9603bHorst Hummel		return -EINVAL;
99001376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
991645c98c8b6c09eae58ac2f97e0ade6ced4d6443fHorst Hummel	if (val) {
99220c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber		rc = dasd_eer_enable(devmap->device);
993645c98c8b6c09eae58ac2f97e0ade6ced4d6443fHorst Hummel		if (rc)
994645c98c8b6c09eae58ac2f97e0ade6ced4d6443fHorst Hummel			return rc;
995645c98c8b6c09eae58ac2f97e0ade6ced4d6443fHorst Hummel	} else
99620c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber		dasd_eer_disable(devmap->device);
997645c98c8b6c09eae58ac2f97e0ade6ced4d6443fHorst Hummel	return count;
99820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber}
99920c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber
100020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberstatic DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
100120c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct attribute * dasd_attrs[] = {
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&dev_attr_readonly.attr,
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&dev_attr_discipline.attr,
10054dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	&dev_attr_status.attr,
10063d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	&dev_attr_alias.attr,
10073d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	&dev_attr_vendor.attr,
10083d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	&dev_attr_uid.attr,
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&dev_attr_use_diag.attr,
101020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	&dev_attr_eer_enabled.attr,
10119575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	&dev_attr_erplog.attr,
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NULL,
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct attribute_group dasd_attr_group = {
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.attrs = dasd_attrs,
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1019405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel/*
10203d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel * Return copy of the device unique identifier.
10213d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel */
10223d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelint
10233d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummeldasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
10243d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{
10253d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	struct dasd_devmap *devmap;
10263d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10273d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	devmap = dasd_find_busid(cdev->dev.bus_id);
10283d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	if (IS_ERR(devmap))
10293d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel		return PTR_ERR(devmap);
10303d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	spin_lock(&dasd_devmap_lock);
10313d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	*uid = devmap->uid;
10323d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	spin_unlock(&dasd_devmap_lock);
10333d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	return 0;
10343d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel}
10353d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10363d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel/*
10373d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel * Register the given device unique identifier into devmap struct.
1038b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter * In addition check if the related storage server subsystem ID is already
1039b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter * contained in the dasd_server_ssid_list. If subsystem ID is not contained,
1040b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter * create new entry.
1041405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel * Return 0 if server was already in serverlist,
1042405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel *	  1 if the server was added successful
1043405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel *	 <0 in case of error.
10443d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel */
10453d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelint
10463d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummeldasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
10473d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{
10483d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	struct dasd_devmap *devmap;
10493d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10503d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	devmap = dasd_find_busid(cdev->dev.bus_id);
10513d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	if (IS_ERR(devmap))
10523d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel		return PTR_ERR(devmap);
1053d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel
10543d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	spin_lock(&dasd_devmap_lock);
10553d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	devmap->uid = *uid;
10563d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	spin_unlock(&dasd_devmap_lock);
1057d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel
10588e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	return 0;
10593d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel}
1060405455734e1cdec09c37233216f9240cb1a058e5Horst HummelEXPORT_SYMBOL_GPL(dasd_set_uid);
10613d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
1062f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel/*
1063f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel * Return value of the specified feature.
1064f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel */
1065f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummelint
1066f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummeldasd_get_feature(struct ccw_device *cdev, int feature)
1067f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel{
1068f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	struct dasd_devmap *devmap;
1069f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
1070f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	devmap = dasd_find_busid(cdev->dev.bus_id);
1071f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	if (IS_ERR(devmap))
1072405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel		return PTR_ERR(devmap);
1073f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
1074f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	return ((devmap->features & feature) != 0);
1075f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel}
1076f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
1077f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel/*
1078f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel * Set / reset given feature.
1079f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel * Flag indicates wether to set (!=0) or the reset (=0) the feature.
1080f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel */
1081f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummelint
1082f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummeldasd_set_feature(struct ccw_device *cdev, int feature, int flag)
1083f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel{
1084f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	struct dasd_devmap *devmap;
1085f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
1086f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	devmap = dasd_find_busid(cdev->dev.bus_id);
1087f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	if (IS_ERR(devmap))
1088405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel		return PTR_ERR(devmap);
1089f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
1090f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	spin_lock(&dasd_devmap_lock);
1091f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	if (flag)
1092f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel		devmap->features |= feature;
1093f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	else
1094f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel		devmap->features &= ~feature;
1095c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel	if (devmap->device)
1096c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel		devmap->device->features = devmap->features;
1097f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	spin_unlock(&dasd_devmap_lock);
1098f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	return 0;
1099f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel}
1100f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
1101f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_add_sysfs_files(struct ccw_device *cdev)
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_remove_sysfs_files(struct ccw_device *cdev)
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_devmap_init(void)
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize devmap structures. */
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dasd_max_devindex = 0;
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 256; i++)
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		INIT_LIST_HEAD(&dasd_hashlists[i]);
1124405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	return 0;
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_devmap_exit(void)
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dasd_forget_ranges();
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1132