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
16fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland#define KMSG_COMPONENT "dasd"
17fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ctype.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
208d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russell#include <linux/module.h>
215a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/debug.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
257039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter#include <asm/ipl.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is ugly... */
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PRINTK_HEADER "dasd_devmap:"
2998df67b324a2a986987ce29986e44ae9156b6698Kay Sievers#define DASD_BUS_ID_SIZE 20
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "dasd_int.h"
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33e18b890bb0881bbab6f4f1a6cd20d9c60d66b003Christoph Lameterstruct kmem_cache *dasd_page_cache;
34405455734e1cdec09c37233216f9240cb1a058e5Horst HummelEXPORT_SYMBOL_GPL(dasd_page_cache);
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dasd_devmap_t is used to store the features and the relation
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * between device number and device index. To find a dasd_devmap_t
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that corresponds to a device number of a device index each
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dasd_devmap_t is added to two linked lists, one to search by
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the device number and one to search by the device index. As
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * soon as big minor numbers are available the device index list
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can be removed since the device number will then be identical
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the device index.
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_devmap {
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head list;
4898df67b324a2a986987ce29986e44ae9156b6698Kay Sievers	char bus_id[DASD_BUS_ID_SIZE];
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int devindex;
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned short features;
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_device *device;
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Parameter parsing functions for dasd= parameter. The syntax is:
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <devno>		: (0x)?[0-9a-fA-F]+
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <busid>		: [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <feature>		: ro
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <feature_list>	: \(<feature>(:<feature>)*\)
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <devno-range>	: <devno>(-<devno>)?<feature_list>?
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <busid-range>	: <busid>(-<busid>)?<feature_list>?
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <devices>		: <devno-range>|<busid-range>
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <dasd_module>	: dasd_diag_mod|dasd_eckd_mod|dasd_fba_mod
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <dasd>		: autodetect|probeonly|<devices>(,<devices>)*
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dasd_probeonly =  0;	/* is true, when probeonly mode is active */
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dasd_autodetect = 0;	/* is true, when autodetection is active */
70405455734e1cdec09c37233216f9240cb1a058e5Horst Hummelint dasd_nopav = 0;		/* is true, when PAV is disabled */
71405455734e1cdec09c37233216f9240cb1a058e5Horst HummelEXPORT_SYMBOL_GPL(dasd_nopav);
72f3eb5384cf0325c02e306b1d81e70f81a03d7432Stefan Weinhuberint dasd_nofcx;			/* disable High Performance Ficon */
73f3eb5384cf0325c02e306b1d81e70f81a03d7432Stefan WeinhuberEXPORT_SYMBOL_GPL(dasd_nofcx);
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * char *dasd[] is intended to hold the ranges supplied by the dasd= statement
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it is named 'dasd' to directly be filled by insmod with the comma separated
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * strings when running as a module.
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *dasd[256];
818d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param_array(dasd, charp, NULL, 0);
828d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russell
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
84d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel * Single spinlock to protect devmap and servermap structures and lists.
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(dasd_devmap_lock);
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Hash lists for devmap structures.
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct list_head dasd_hashlists[256];
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dasd_max_devindex;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9469f90f6a5650a74dd8f428e8d2f05859d58da3d7Cornelia Huckstatic struct dasd_devmap *dasd_add_busid(const char *, int);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
9769f90f6a5650a74dd8f428e8d2f05859d58da3d7Cornelia Huckdasd_hash_busid(const char *bus_id)
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int hash, i;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hash = 0;
10298df67b324a2a986987ce29986e44ae9156b6698Kay Sievers	for (i = 0; (i < DASD_BUS_ID_SIZE) && *bus_id; i++, bus_id++)
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hash += *bus_id;
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return hash & 0xff;
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef MODULE
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The parameter parsing functions for builtin-drivers are called
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * before kmalloc works. Store the pointers to the parameters strings
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * into dasd[] for later processing.
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_call_setup(char *str)
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static int count = 0;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count < 256)
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd[count++] = str;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__setup ("dasd=", dasd_call_setup);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* #ifndef MODULE */
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1267039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter#define	DASD_IPLDEV	"ipldev"
1277039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read a device busid/devno from a string.
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1314d284cac76d0bfebc42d76b428c4e44d921200a9Heiko Carstensstatic int
132fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_busid(char **str, int *id0, int *id1, int *devno)
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val, old_style;
136138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel
1377039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter	/* Interpret ipldev busid */
1387039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter	if (strncmp(DASD_IPLDEV, *str, strlen(DASD_IPLDEV)) == 0) {
1397039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		if (ipl_info.type != IPL_TYPE_CCW) {
140fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland			pr_err("The IPL device is not a CCW device\n");
1417039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter			return -EINVAL;
1427039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		}
1437039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		*id0 = 0;
1447039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		*id1 = ipl_info.data.ccw.dev_id.ssid;
1457039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		*devno = ipl_info.data.ccw.dev_id.devno;
1467039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		*str += strlen(DASD_IPLDEV);
1477039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter
1487039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter		return 0;
1497039d3a11c4b4b59f9ef933b4b0a28304bdd07d1Peter Oberparleiter	}
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check for leading '0x' */
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	old_style = 0;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((*str)[0] == '0' && (*str)[1] == 'x') {
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*str += 2;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		old_style = 1;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(*str, str, 16);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (old_style || (*str)[0] != '.') {
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*id0 = *id1 = 0;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val < 0 || val > 0xffff)
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*devno = val;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* New style x.y.z busid */
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val < 0 || val > 0xff)
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*id0 = val;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(*str)++;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(*str, str, 16);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val < 0 || val > 0xff || (*str)++[0] != '.')
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*id1 = val;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(*str, str, 16);
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val < 0 || val > 0xffff)
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*devno = val;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read colon separated list of dasd features. Currently there is
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * only one: "ro" for read-only devices. The default feature set
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is empty (value 0).
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1914d284cac76d0bfebc42d76b428c4e44d921200a9Heiko Carstensstatic int
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_feature_list(char *str, char **endp)
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int features, len, rc;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = 0;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*str != '(') {
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*endp = str;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return DASD_FEATURE_DEFAULT;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	str++;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	features = 0;
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (1) {
205138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel		for (len = 0;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     str[len] && str[len] != ':' && str[len] != ')'; len++);
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (len == 2 && !strncmp(str, "ro", 2))
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			features |= DASD_FEATURE_READONLY;
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else if (len == 4 && !strncmp(str, "diag", 4))
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			features |= DASD_FEATURE_USEDIAG;
211e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland		else if (len == 3 && !strncmp(str, "raw", 3))
212e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland			features |= DASD_FEATURE_USERAW;
2139575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		else if (len == 6 && !strncmp(str, "erplog", 6))
2149575bf265711cabe7147a68003a56a9f19f034daHorst Hummel			features |= DASD_FEATURE_ERPLOG;
21513de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski		else if (len == 8 && !strncmp(str, "failfast", 8))
21613de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski			features |= DASD_FEATURE_FAILFAST;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
218fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland			pr_warning("%*s is not a supported device option\n",
219fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland				   len, str);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rc = -EINVAL;
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str += len;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (*str != ':')
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str++;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*str != ')') {
228fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland		pr_warning("A closing parenthesis ')' is missing in the "
229fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland			   "dasd= parameter\n");
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = -EINVAL;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str++;
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*endp = str;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc != 0)
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return rc;
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return features;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try to match the first element on the comma separated parse string
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with one of the known keywords. If a keyword is found, take the approprate
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * action and return a pointer to the residual string. If the first element
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * could not be matched to any keyword then return an error code.
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse_keyword( char *parsestring ) {
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *nextcomma, *residual_str;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int length;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nextcomma = strchr(parsestring,',');
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nextcomma) {
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		length = nextcomma - parsestring;
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		residual_str = nextcomma + 1;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		length = strlen(parsestring);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		residual_str = parsestring + length;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
259405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	if (strncmp("autodetect", parsestring, length) == 0) {
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_autodetect = 1;
261fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland		pr_info("The autodetection mode has been activated\n");
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                return residual_str;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
264405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	if (strncmp("probeonly", parsestring, length) == 0) {
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_probeonly = 1;
266fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland		pr_info("The probeonly mode has been activated\n");
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                return residual_str;
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
269405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	if (strncmp("nopav", parsestring, length) == 0) {
270dcd707b4bdc10b4fa20efa116dbaeded21513115Peter Oberparleiter		if (MACHINE_IS_VM)
271fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland			pr_info("'nopav' is not supported on z/VM\n");
272dcd707b4bdc10b4fa20efa116dbaeded21513115Peter Oberparleiter		else {
273dcd707b4bdc10b4fa20efa116dbaeded21513115Peter Oberparleiter			dasd_nopav = 1;
274fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland			pr_info("PAV support has be deactivated\n");
275dcd707b4bdc10b4fa20efa116dbaeded21513115Peter Oberparleiter		}
276405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel		return residual_str;
277405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	}
278f3eb5384cf0325c02e306b1d81e70f81a03d7432Stefan Weinhuber	if (strncmp("nofcx", parsestring, length) == 0) {
279f3eb5384cf0325c02e306b1d81e70f81a03d7432Stefan Weinhuber		dasd_nofcx = 1;
280fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland		pr_info("High Performance FICON support has been "
281fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland			"deactivated\n");
282f3eb5384cf0325c02e306b1d81e70f81a03d7432Stefan Weinhuber		return residual_str;
283f3eb5384cf0325c02e306b1d81e70f81a03d7432Stefan Weinhuber	}
284405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	if (strncmp("fixedbuffers", parsestring, length) == 0) {
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dasd_page_cache)
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return residual_str;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_page_cache =
2882f6c55fc3109bcfa1bb1a112c825e07212c20f37Heiko Carstens			kmem_cache_create("dasd_page_cache", PAGE_SIZE,
2892f6c55fc3109bcfa1bb1a112c825e07212c20f37Heiko Carstens					  PAGE_SIZE, SLAB_CACHE_DMA,
29020c2df83d25c6a95affe6157a4c9cac4cf5ffaacPaul Mundt					  NULL);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!dasd_page_cache)
292fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland			DBF_EVENT(DBF_WARNING, "%s", "Failed to create slab, "
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"fixed buffer mode disabled.");
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
295fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland			DBF_EVENT(DBF_INFO, "%s",
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 "turning on fixed buffer mode");
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                return residual_str;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ERR_PTR(-EINVAL);
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try to interprete the first element on the comma separated parse string
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as a device number or a range of devices. If the interpretation is
30525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * successful, create the matching dasd_devmap entries and return a pointer
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the residual string.
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If interpretation fails or in case of an error, return an error code.
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse_range( char *parsestring ) {
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int from, from_id0, from_id1;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int to, to_id0, to_id1;
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int features, rc;
31698df67b324a2a986987ce29986e44ae9156b6698Kay Sievers	char bus_id[DASD_BUS_ID_SIZE+1], *str;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	str = parsestring;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = dasd_busid(&str, &from_id0, &from_id1, &from);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc == 0) {
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to = from;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to_id0 = from_id0;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to_id1 = from_id1;
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (*str == '-') {
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			str++;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rc = dasd_busid(&str, &to_id0, &to_id1, &to);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc == 0 &&
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (from_id0 != to_id0 || from_id1 != to_id1 || from > to))
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = -EINVAL;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc) {
333fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland		pr_err("%s is not a valid device range\n", parsestring);
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(rc);
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	features = dasd_feature_list(str, &str);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (features < 0)
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(-EINVAL);
339405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	/* each device in dasd= parameter should be set initially online */
340405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	features |= DASD_FEATURE_INITIAL_ONLINE;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (from <= to) {
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sprintf(bus_id, "%01x.%01x.%04x",
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			from_id0, from_id1, from++);
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		devmap = dasd_add_busid(bus_id, features);
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (IS_ERR(devmap))
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (char *)devmap;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*str == ',')
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return str + 1;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*str == '\0')
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return str;
352fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland	pr_warning("The dasd= parameter value %s has an invalid ending\n",
353fc19f381b3828aa4f8a3417dbefc3418ec6bbe10Stefan Haberland		   str);
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ERR_PTR(-EINVAL);
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3574d284cac76d0bfebc42d76b428c4e44d921200a9Heiko Carstensstatic char *
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse_next_element( char *parsestring ) {
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char * residual_str;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	residual_str = dasd_parse_keyword(parsestring);
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!IS_ERR(residual_str))
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return residual_str;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	residual_str = dasd_parse_range(parsestring);
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return residual_str;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Parse parameters stored in dasd[]
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The 'dasd=...' parameter allows to specify a comma separated list of
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * keywords and device ranges. When the dasd driver is build into the kernel,
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the complete list will be stored as one element of the dasd[] array.
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When the dasd driver is build as a module, then the list is broken into
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it's elements and each dasd[] entry contains one element.
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse(void)
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc, i;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *parsestring;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = 0;
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 256; i++) {
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dasd[i] == NULL)
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		parsestring = dasd[i];
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* loop over the comma separated list in the parsestring */
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (*parsestring) {
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			parsestring = dasd_parse_next_element(parsestring);
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if(IS_ERR(parsestring)) {
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rc = PTR_ERR(parsestring);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc) {
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DBF_EVENT(DBF_ALERT, "%s", "invalid range found");
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Add a devmap for the device specified by busid. It is possible that
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the devmap already exists (dasd= parameter). The order of the devices
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * added through this function will define the kdevs for the individual
406138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel * devices.
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dasd_devmap *
40969f90f6a5650a74dd8f428e8d2f05859d58da3d7Cornelia Huckdasd_add_busid(const char *bus_id, int features)
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap, *new, *tmp;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int hash;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new = (struct dasd_devmap *)
415138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel		kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!new)
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(-ENOMEM);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
419d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens	devmap = NULL;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hash = dasd_hash_busid(bus_id);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(tmp, &dasd_hashlists[hash], list)
42298df67b324a2a986987ce29986e44ae9156b6698Kay Sievers		if (strncmp(tmp->bus_id, bus_id, DASD_BUS_ID_SIZE) == 0) {
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			devmap = tmp;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!devmap) {
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* This bus_id is new. */
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		new->devindex = dasd_max_devindex++;
42998df67b324a2a986987ce29986e44ae9156b6698Kay Sievers		strncpy(new->bus_id, bus_id, DASD_BUS_ID_SIZE);
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		new->features = features;
431d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens		new->device = NULL;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_add(&new->list, &dasd_hashlists[hash]);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		devmap = new;
434d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens		new = NULL;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
43717fd682e544556a2a829e94383239c029bb21c5eJesper Juhl	kfree(new);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return devmap;
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find devmap for device with given bus_id.
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dasd_devmap *
44569f90f6a5650a74dd8f428e8d2f05859d58da3d7Cornelia Huckdasd_find_busid(const char *bus_id)
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap, *tmp;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int hash;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = ERR_PTR(-ENODEV);
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hash = dasd_hash_busid(bus_id);
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(tmp, &dasd_hashlists[hash], list) {
45498df67b324a2a986987ce29986e44ae9156b6698Kay Sievers		if (strncmp(tmp->bus_id, bus_id, DASD_BUS_ID_SIZE) == 0) {
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			devmap = tmp;
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return devmap;
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check if busid has been added to the list of dasd ranges.
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
46769f90f6a5650a74dd8f428e8d2f05859d58da3d7Cornelia Huckdasd_busid_known(const char *bus_id)
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0;
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Forget all about the device numbers added so far.
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This may only be called at module unload or system shutdown.
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_forget_ranges(void)
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap, *n;
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 256; i++) {
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) {
485606f44228e257ea1e35557c2fec7133cca634096Eric Sesterhenn			BUG_ON(devmap->device != NULL);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_del(&devmap->list);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kfree(devmap);
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find the device struct by its device index.
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_device *
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_device_from_devindex(int devindex)
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap, *tmp;
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_device *device;
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
504d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens	devmap = NULL;
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; (i < 256) && !devmap; i++)
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_for_each_entry(tmp, &dasd_hashlists[i], list)
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tmp->devindex == devindex) {
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Found the devmap for the device. */
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				devmap = tmp;
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (devmap && devmap->device) {
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		device = devmap->device;
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_get_device(device);
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		device = ERR_PTR(-ENODEV);
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return device;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return devmap for cdev. If no devmap exists yet, create one and
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * connect it to the cdev.
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dasd_devmap *
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_devmap_from_cdev(struct ccw_device *cdev)
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5302a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers	devmap = dasd_find_busid(dev_name(&cdev->dev));
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(devmap))
5322a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers		devmap = dasd_add_busid(dev_name(&cdev->dev),
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					DASD_FEATURE_DEFAULT);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return devmap;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Create a dasd device structure for cdev.
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_device *
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_create_device(struct ccw_device *cdev)
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_device *device;
545a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	unsigned long flags;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc;
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = dasd_devmap_from_cdev(cdev);
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(devmap))
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (void *) devmap;
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device = dasd_alloc_device();
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(device))
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return device;
555a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	atomic_set(&device->ref_count, 3);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!devmap->device) {
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		devmap->device = device;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		device->devindex = devmap->devindex;
561c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel		device->features = devmap->features;
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		get_device(&cdev->dev);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		device->cdev = cdev;
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = 0;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Someone else was faster. */
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = -EBUSY;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc) {
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_free_device(device);
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(rc);
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
574a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky
575a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
576faf16aa9b368d48a0efbd0920718d68ec7a72542Cornelia Huck	dev_set_drvdata(&cdev->dev, device);
577a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
578a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return device;
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wait queue for dasd_delete_device waits.
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Remove a dasd device structure. The passed referenced
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is destroyed.
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_delete_device(struct dasd_device *device)
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ccw_device *cdev;
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
596a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	unsigned long flags;
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* First remove device pointer from devmap. */
5992a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers	devmap = dasd_find_busid(dev_name(&device->cdev->dev));
600606f44228e257ea1e35557c2fec7133cca634096Eric Sesterhenn	BUG_ON(IS_ERR(devmap));
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (devmap->device != device) {
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock(&dasd_devmap_lock);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dasd_put_device(device);
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap->device = NULL;
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
610a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	/* Disconnect dasd_device structure from ccw_device structure. */
611a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
612faf16aa9b368d48a0efbd0920718d68ec7a72542Cornelia Huck	dev_set_drvdata(&device->cdev->dev, NULL);
613a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
614a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky
615a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	/*
616a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	 * Drop ref_count by 3, one for the devmap reference, one for
617a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	 * the cdev reference and one for the passed reference.
618a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	 */
619a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	atomic_sub(3, &device->ref_count);
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Wait for reference counter to drop to zero. */
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Disconnect dasd_device structure from ccw_device structure. */
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cdev = device->cdev;
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device->cdev = NULL;
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Put ccw_device structure. */
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_device(&cdev->dev);
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now the device structure can be freed. */
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dasd_free_device(device);
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reference counter dropped to zero. Wake up waiter
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in dasd_delete_device.
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_put_device_wake(struct dasd_device *device)
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wake_up(&dasd_delete_wq);
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
644a4d26c6aeceea330ee5e0fb6b017d57e3b252d29Stefan WeinhuberEXPORT_SYMBOL_GPL(dasd_put_device_wake);
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return dasd_device structure associated with cdev.
648a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky * This function needs to be called with the ccw device
649a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky * lock held. It can be used from interrupt context.
650a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky */
651a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefskystruct dasd_device *
652a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefskydasd_device_from_cdev_locked(struct ccw_device *cdev)
653a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky{
654faf16aa9b368d48a0efbd0920718d68ec7a72542Cornelia Huck	struct dasd_device *device = dev_get_drvdata(&cdev->dev);
655a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky
656a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	if (!device)
657a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky		return ERR_PTR(-ENODEV);
658a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	dasd_get_device(device);
659a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	return device;
660a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky}
661a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky
662a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky/*
663a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky * Return dasd_device structure associated with cdev.
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_device *
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_device_from_cdev(struct ccw_device *cdev)
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_device *device;
669a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	unsigned long flags;
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
672a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	device = dasd_device_from_cdev_locked(cdev);
673a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return device;
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
67765f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhubervoid dasd_add_link_to_gendisk(struct gendisk *gdp, struct dasd_device *device)
67865f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber{
67965f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	struct dasd_devmap *devmap;
68065f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber
68165f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	devmap = dasd_find_busid(dev_name(&device->cdev->dev));
68265f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	if (IS_ERR(devmap))
68365f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber		return;
68465f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	spin_lock(&dasd_devmap_lock);
68565f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	gdp->private_data = devmap;
68665f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	spin_unlock(&dasd_devmap_lock);
68765f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber}
68865f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber
68965f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuberstruct dasd_device *dasd_device_from_gendisk(struct gendisk *gdp)
69065f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber{
69165f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	struct dasd_device *device;
69265f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	struct dasd_devmap *devmap;
69365f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber
69465f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	if (!gdp->private_data)
69565f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber		return NULL;
69665f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	device = NULL;
69765f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	spin_lock(&dasd_devmap_lock);
69865f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	devmap = gdp->private_data;
69965f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	if (devmap && devmap->device) {
70065f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber		device = devmap->device;
70165f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber		dasd_get_device(device);
70265f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	}
70365f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	spin_unlock(&dasd_devmap_lock);
70465f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber	return device;
70565f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber}
70665f8da475995f667af5298c644707dbd9d646ca6Stefan Weinhuber
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SECTION: files in sysfs
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
71213de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski * failfast controls the behaviour, if no path is available
71313de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski */
71413de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinskistatic ssize_t dasd_ff_show(struct device *dev, struct device_attribute *attr,
71513de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski			    char *buf)
71613de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski{
71713de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	struct dasd_devmap *devmap;
71813de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	int ff_flag;
71913de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski
720ca0b4b7d2cb57a2e24d7e48ce9b411b9baa3bf63Cornelia Huck	devmap = dasd_find_busid(dev_name(dev));
72113de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	if (!IS_ERR(devmap))
72213de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski		ff_flag = (devmap->features & DASD_FEATURE_FAILFAST) != 0;
72313de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	else
72413de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski		ff_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_FAILFAST) != 0;
72513de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	return snprintf(buf, PAGE_SIZE, ff_flag ? "1\n" : "0\n");
72613de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski}
72713de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski
72813de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinskistatic ssize_t dasd_ff_store(struct device *dev, struct device_attribute *attr,
72913de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	      const char *buf, size_t count)
73013de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski{
73113de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	struct dasd_devmap *devmap;
73213de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	int val;
73313de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	char *endp;
73413de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski
73513de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
73613de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	if (IS_ERR(devmap))
73713de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski		return PTR_ERR(devmap);
73813de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski
73913de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	val = simple_strtoul(buf, &endp, 0);
74013de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	if (((endp + 1) < (buf + count)) || (val > 1))
74113de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski		return -EINVAL;
74213de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski
74313de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	spin_lock(&dasd_devmap_lock);
74413de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	if (val)
74513de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski		devmap->features |= DASD_FEATURE_FAILFAST;
74613de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	else
74713de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski		devmap->features &= ~DASD_FEATURE_FAILFAST;
74813de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	if (devmap->device)
74913de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski		devmap->device->features = devmap->features;
75013de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	spin_unlock(&dasd_devmap_lock);
75113de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	return count;
75213de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski}
75313de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski
75413de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinskistatic DEVICE_ATTR(failfast, 0644, dasd_ff_show, dasd_ff_store);
75513de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski
75613de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski/*
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * readonly controls the readonly status of a dasd
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
760e404e274f62665f3333d6a539d0d3701f678a598Yani Ioannoudasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ro_flag;
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7652a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers	devmap = dasd_find_busid(dev_name(dev));
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!IS_ERR(devmap))
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
774138c014dcba74211dc4e835658f34a787c40cf17Horst Hummeldasd_ro_store(struct device *dev, struct device_attribute *attr,
775138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel	      const char *buf, size_t count)
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
77833b62a30f78536b976183cc764c08038ac011e0aStefan Weinhuber	struct dasd_device *device;
77901376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	int val;
78001376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	char *endp;
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(devmap))
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return PTR_ERR(devmap);
78501376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
78601376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	val = simple_strtoul(buf, &endp, 0);
78701376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	if (((endp + 1) < (buf + count)) || (val > 1))
78801376f4495840f3daf6d73679242b5964fc9603bHorst Hummel		return -EINVAL;
78901376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
79101376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	if (val)
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		devmap->features |= DASD_FEATURE_READONLY;
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		devmap->features &= ~DASD_FEATURE_READONLY;
79533b62a30f78536b976183cc764c08038ac011e0aStefan Weinhuber	device = devmap->device;
79633b62a30f78536b976183cc764c08038ac011e0aStefan Weinhuber	if (device) {
79733b62a30f78536b976183cc764c08038ac011e0aStefan Weinhuber		device->features = devmap->features;
79833b62a30f78536b976183cc764c08038ac011e0aStefan Weinhuber		val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags);
79933b62a30f78536b976183cc764c08038ac011e0aStefan Weinhuber	}
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
80133b62a30f78536b976183cc764c08038ac011e0aStefan Weinhuber	if (device && device->block && device->block->gdp)
80233b62a30f78536b976183cc764c08038ac011e0aStefan Weinhuber		set_disk_ro(device->block->gdp, val);
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
8079575bf265711cabe7147a68003a56a9f19f034daHorst Hummel/*
8089575bf265711cabe7147a68003a56a9f19f034daHorst Hummel * erplog controls the logging of ERP related data
8099575bf265711cabe7147a68003a56a9f19f034daHorst Hummel * (e.g. failing channel programs).
8109575bf265711cabe7147a68003a56a9f19f034daHorst Hummel */
8119575bf265711cabe7147a68003a56a9f19f034daHorst Hummelstatic ssize_t
8129575bf265711cabe7147a68003a56a9f19f034daHorst Hummeldasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
8139575bf265711cabe7147a68003a56a9f19f034daHorst Hummel{
8149575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	struct dasd_devmap *devmap;
8159575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	int erplog;
8169575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
8172a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers	devmap = dasd_find_busid(dev_name(dev));
8189575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	if (!IS_ERR(devmap))
8199575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
8209575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	else
8219575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		erplog = (DASD_FEATURE_DEFAULT & DASD_FEATURE_ERPLOG) != 0;
8229575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	return snprintf(buf, PAGE_SIZE, erplog ? "1\n" : "0\n");
8239575bf265711cabe7147a68003a56a9f19f034daHorst Hummel}
8249575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
8259575bf265711cabe7147a68003a56a9f19f034daHorst Hummelstatic ssize_t
8269575bf265711cabe7147a68003a56a9f19f034daHorst Hummeldasd_erplog_store(struct device *dev, struct device_attribute *attr,
8279575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	      const char *buf, size_t count)
8289575bf265711cabe7147a68003a56a9f19f034daHorst Hummel{
8299575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	struct dasd_devmap *devmap;
8309575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	int val;
8319575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	char *endp;
8329575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
8339575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
8349575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	if (IS_ERR(devmap))
8359575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		return PTR_ERR(devmap);
8369575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
8379575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	val = simple_strtoul(buf, &endp, 0);
8389575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	if (((endp + 1) < (buf + count)) || (val > 1))
8399575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		return -EINVAL;
8409575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
8419575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	spin_lock(&dasd_devmap_lock);
8429575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	if (val)
8439575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		devmap->features |= DASD_FEATURE_ERPLOG;
8449575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	else
8459575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		devmap->features &= ~DASD_FEATURE_ERPLOG;
8469575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	if (devmap->device)
8479575bf265711cabe7147a68003a56a9f19f034daHorst Hummel		devmap->device->features = devmap->features;
8489575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	spin_unlock(&dasd_devmap_lock);
8499575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	return count;
8509575bf265711cabe7147a68003a56a9f19f034daHorst Hummel}
8519575bf265711cabe7147a68003a56a9f19f034daHorst Hummel
8529575bf265711cabe7147a68003a56a9f19f034daHorst Hummelstatic DEVICE_ATTR(erplog, 0644, dasd_erplog_show, dasd_erplog_store);
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * use_diag controls whether the driver should use diag rather than ssch
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to talk to the device
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
858138c014dcba74211dc4e835658f34a787c40cf17Horst Hummelstatic ssize_t
859e404e274f62665f3333d6a539d0d3701f678a598Yani Ioannoudasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int use_diag;
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8642a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers	devmap = dasd_find_busid(dev_name(dev));
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!IS_ERR(devmap))
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, use_diag ? "1\n" : "0\n");
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
873138c014dcba74211dc4e835658f34a787c40cf17Horst Hummeldasd_use_diag_store(struct device *dev, struct device_attribute *attr,
874138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel		    const char *buf, size_t count)
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dasd_devmap *devmap;
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ssize_t rc;
87801376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	int val;
87901376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	char *endp;
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(devmap))
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return PTR_ERR(devmap);
88401376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
88501376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	val = simple_strtoul(buf, &endp, 0);
88601376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	if (((endp + 1) < (buf + count)) || (val > 1))
88701376f4495840f3daf6d73679242b5964fc9603bHorst Hummel		return -EINVAL;
88801376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&dasd_devmap_lock);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Changing diag discipline flag is only allowed in offline state. */
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = count;
892e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	if (!devmap->device && !(devmap->features & DASD_FEATURE_USERAW)) {
89301376f4495840f3daf6d73679242b5964fc9603bHorst Hummel		if (val)
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			devmap->features |= DASD_FEATURE_USEDIAG;
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			devmap->features &= ~DASD_FEATURE_USEDIAG;
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = -EPERM;
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&dasd_devmap_lock);
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
903138c014dcba74211dc4e835658f34a787c40cf17Horst Hummelstatic DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
905e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland/*
906e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland * use_raw controls whether the driver should give access to raw eckd data or
907e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland * operate in standard mode
908e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland */
909e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberlandstatic ssize_t
910e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberlanddasd_use_raw_show(struct device *dev, struct device_attribute *attr, char *buf)
911e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland{
912e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	struct dasd_devmap *devmap;
913e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	int use_raw;
914e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland
915e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	devmap = dasd_find_busid(dev_name(dev));
916e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	if (!IS_ERR(devmap))
917e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland		use_raw = (devmap->features & DASD_FEATURE_USERAW) != 0;
918e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	else
919e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland		use_raw = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USERAW) != 0;
920e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	return sprintf(buf, use_raw ? "1\n" : "0\n");
921e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland}
922e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland
923e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberlandstatic ssize_t
924e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberlanddasd_use_raw_store(struct device *dev, struct device_attribute *attr,
925e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland		    const char *buf, size_t count)
926e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland{
927e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	struct dasd_devmap *devmap;
928e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	ssize_t rc;
929e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	unsigned long val;
930e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland
931e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
932e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	if (IS_ERR(devmap))
933e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland		return PTR_ERR(devmap);
934e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland
935e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	if ((strict_strtoul(buf, 10, &val) != 0) || val > 1)
936e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland		return -EINVAL;
937e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland
938e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	spin_lock(&dasd_devmap_lock);
939e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	/* Changing diag discipline flag is only allowed in offline state. */
940e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	rc = count;
941e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	if (!devmap->device && !(devmap->features & DASD_FEATURE_USEDIAG)) {
942e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland		if (val)
943e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland			devmap->features |= DASD_FEATURE_USERAW;
944e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland		else
945e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland			devmap->features &= ~DASD_FEATURE_USERAW;
946e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	} else
947e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland		rc = -EPERM;
948e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	spin_unlock(&dasd_devmap_lock);
949e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	return rc;
950e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland}
951e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland
952e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberlandstatic DEVICE_ATTR(raw_track_access, 0644, dasd_use_raw_show,
953e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland		   dasd_use_raw_store);
954e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
956138c014dcba74211dc4e835658f34a787c40cf17Horst Hummeldasd_discipline_show(struct device *dev, struct device_attribute *attr,
957138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel		     char *buf)
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
959a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	struct dasd_device *device;
960a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	ssize_t len;
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
962a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	device = dasd_device_from_cdev(to_ccwdev(dev));
963589c74d5076dd1bde13a5a36d97ca79be8bd72b2Stefan Haberland	if (IS_ERR(device))
964589c74d5076dd1bde13a5a36d97ca79be8bd72b2Stefan Haberland		goto out;
965589c74d5076dd1bde13a5a36d97ca79be8bd72b2Stefan Haberland	else if (!device->discipline) {
966589c74d5076dd1bde13a5a36d97ca79be8bd72b2Stefan Haberland		dasd_put_device(device);
967589c74d5076dd1bde13a5a36d97ca79be8bd72b2Stefan Haberland		goto out;
968589c74d5076dd1bde13a5a36d97ca79be8bd72b2Stefan Haberland	} else {
969a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky		len = snprintf(buf, PAGE_SIZE, "%s\n",
970a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky			       device->discipline->name);
971a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky		dasd_put_device(device);
972589c74d5076dd1bde13a5a36d97ca79be8bd72b2Stefan Haberland		return len;
973589c74d5076dd1bde13a5a36d97ca79be8bd72b2Stefan Haberland	}
974589c74d5076dd1bde13a5a36d97ca79be8bd72b2Stefan Haberlandout:
975589c74d5076dd1bde13a5a36d97ca79be8bd72b2Stefan Haberland	len = snprintf(buf, PAGE_SIZE, "none\n");
976a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky	return len;
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9813d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic ssize_t
9824dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummeldasd_device_status_show(struct device *dev, struct device_attribute *attr,
9834dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		     char *buf)
9844dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel{
9854dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	struct dasd_device *device;
9864dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	ssize_t len;
9874dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel
9884dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	device = dasd_device_from_cdev(to_ccwdev(dev));
9894dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	if (!IS_ERR(device)) {
9904dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		switch (device->state) {
9914dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_NEW:
9924dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "new\n");
9934dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
9944dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_KNOWN:
9954dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "detected\n");
9964dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
9974dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_BASIC:
9984dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "basic\n");
9994dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
10004dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_UNFMT:
10014dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "unformatted\n");
10024dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
10034dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_READY:
10044dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "ready\n");
10054dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
10064dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		case DASD_STATE_ONLINE:
10074dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "online\n");
10084dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
10094dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		default:
10104dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			len = snprintf(buf, PAGE_SIZE, "no stat\n");
10114dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel			break;
10124dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		}
10134dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		dasd_put_device(device);
10144dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	} else
10154dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel		len = snprintf(buf, PAGE_SIZE, "unknown\n");
10164dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	return len;
10174dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel}
10184dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel
10194dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummelstatic DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL);
10204dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel
10212dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberlandstatic ssize_t dasd_alias_show(struct device *dev,
10222dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			       struct device_attribute *attr, char *buf)
10233d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{
10242dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	struct dasd_device *device;
10252dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	struct dasd_uid uid;
10263d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10272dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	device = dasd_device_from_cdev(to_ccwdev(dev));
10282dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	if (IS_ERR(device))
10298e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber		return sprintf(buf, "0\n");
10302dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland
10312dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	if (device->discipline && device->discipline->get_uid &&
10322dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	    !device->discipline->get_uid(device, &uid)) {
10332dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland		if (uid.type == UA_BASE_PAV_ALIAS ||
10340abccf77402af44855da739b439d01cfb65b4bfdStefan Haberland		    uid.type == UA_HYPER_PAV_ALIAS) {
10350abccf77402af44855da739b439d01cfb65b4bfdStefan Haberland			dasd_put_device(device);
10362dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			return sprintf(buf, "1\n");
10370abccf77402af44855da739b439d01cfb65b4bfdStefan Haberland		}
10388e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	}
10392dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	dasd_put_device(device);
10402dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland
10412dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	return sprintf(buf, "0\n");
10423d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel}
10433d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10443d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
10453d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10462dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberlandstatic ssize_t dasd_vendor_show(struct device *dev,
10472dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland				struct device_attribute *attr, char *buf)
10483d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{
10492dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	struct dasd_device *device;
10502dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	struct dasd_uid uid;
10513d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	char *vendor;
10523d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10532dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	device = dasd_device_from_cdev(to_ccwdev(dev));
10542dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	vendor = "";
10552dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	if (IS_ERR(device))
10562dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland		return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
10572dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland
10582dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	if (device->discipline && device->discipline->get_uid &&
10592dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	    !device->discipline->get_uid(device, &uid))
10602dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			vendor = uid.vendor;
10612dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland
10622dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	dasd_put_device(device);
10633d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10643d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
10653d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel}
10663d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10673d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
10683d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10693d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel#define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial    */ 14 + 1 +\
10704abb08c24b5fa7b6ad0807c07077f0f216f6788bStefan Weinhuber		     /* SSID   */ 4 + 1 + /* unit addr */ 2 + 1 +\
10714abb08c24b5fa7b6ad0807c07077f0f216f6788bStefan Weinhuber		     /* vduit */ 32 + 1)
10723d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10733d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic ssize_t
10743d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummeldasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
10753d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{
10762dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	struct dasd_device *device;
10772dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	struct dasd_uid uid;
10788e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	char uid_string[UID_STRLEN];
10798e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	char ua_string[3];
10803d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
10812dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	device = dasd_device_from_cdev(to_ccwdev(dev));
10822dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	uid_string[0] = 0;
10832dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	if (IS_ERR(device))
10842dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland		return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
10852dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland
10862dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	if (device->discipline && device->discipline->get_uid &&
10872dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	    !device->discipline->get_uid(device, &uid)) {
10882dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland		switch (uid.type) {
10892dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland		case UA_BASE_DEVICE:
10902dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			snprintf(ua_string, sizeof(ua_string), "%02x",
10912dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland				 uid.real_unit_addr);
10922dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			break;
10932dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland		case UA_BASE_PAV_ALIAS:
10942dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			snprintf(ua_string, sizeof(ua_string), "%02x",
10952dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland				 uid.base_unit_addr);
10962dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			break;
10972dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland		case UA_HYPER_PAV_ALIAS:
10982dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			snprintf(ua_string, sizeof(ua_string), "xx");
10992dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			break;
11002dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland		default:
11012dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			/* should not happen, treat like base device */
11022dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			snprintf(ua_string, sizeof(ua_string), "%02x",
11032dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland				 uid.real_unit_addr);
11042dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			break;
11052dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland		}
11062dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland
11072dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland		if (strlen(uid.vduit) > 0)
11082dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			snprintf(uid_string, sizeof(uid_string),
11092dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland				 "%s.%s.%04x.%s.%s",
11102dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland				 uid.vendor, uid.serial, uid.ssid, ua_string,
11112dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland				 uid.vduit);
11122dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland		else
11132dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland			snprintf(uid_string, sizeof(uid_string),
11142dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland				 "%s.%s.%04x.%s",
11152dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland				 uid.vendor, uid.serial, uid.ssid, ua_string);
11168e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	}
11172dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland	dasd_put_device(device);
11182dedf0d9eadf39660f2e1686b5d36e4a7515803fStefan Haberland
11198e09f21574ea3028d5629e5de759e0b196c690c5Stefan Weinhuber	return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
11203d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel}
11213d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
11223d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel
112320c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber/*
112420c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber * extended error-reporting
112520c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber */
112620c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberstatic ssize_t
112720c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberdasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
112820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber{
112920c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	struct dasd_devmap *devmap;
113020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	int eer_flag;
113120c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber
11322a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers	devmap = dasd_find_busid(dev_name(dev));
113320c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	if (!IS_ERR(devmap) && devmap->device)
113420c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber		eer_flag = dasd_eer_enabled(devmap->device);
113520c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	else
113620c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber		eer_flag = 0;
113720c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n");
113820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber}
113920c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber
114020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberstatic ssize_t
114120c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberdasd_eer_store(struct device *dev, struct device_attribute *attr,
114220c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	       const char *buf, size_t count)
114320c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber{
114420c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	struct dasd_devmap *devmap;
114501376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	int val, rc;
114601376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	char *endp;
114720c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber
114820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
114920c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	if (IS_ERR(devmap))
115020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber		return PTR_ERR(devmap);
115120c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	if (!devmap->device)
115201376f4495840f3daf6d73679242b5964fc9603bHorst Hummel		return -ENODEV;
115301376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
115401376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	val = simple_strtoul(buf, &endp, 0);
115501376f4495840f3daf6d73679242b5964fc9603bHorst Hummel	if (((endp + 1) < (buf + count)) || (val > 1))
115601376f4495840f3daf6d73679242b5964fc9603bHorst Hummel		return -EINVAL;
115701376f4495840f3daf6d73679242b5964fc9603bHorst Hummel
1158645c98c8b6c09eae58ac2f97e0ade6ced4d6443fHorst Hummel	if (val) {
115920c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber		rc = dasd_eer_enable(devmap->device);
1160645c98c8b6c09eae58ac2f97e0ade6ced4d6443fHorst Hummel		if (rc)
1161645c98c8b6c09eae58ac2f97e0ade6ced4d6443fHorst Hummel			return rc;
1162645c98c8b6c09eae58ac2f97e0ade6ced4d6443fHorst Hummel	} else
116320c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber		dasd_eer_disable(devmap->device);
1164645c98c8b6c09eae58ac2f97e0ade6ced4d6443fHorst Hummel	return count;
116520c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber}
116620c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber
116720c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberstatic DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
116820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber
11697c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland/*
11707c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland * expiration time for default requests
11717c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland */
11727c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberlandstatic ssize_t
11737c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberlanddasd_expires_show(struct device *dev, struct device_attribute *attr, char *buf)
11747c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland{
11757c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	struct dasd_device *device;
11767c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	int len;
11777c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland
11787c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	device = dasd_device_from_cdev(to_ccwdev(dev));
11797c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	if (IS_ERR(device))
11807c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland		return -ENODEV;
11817c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	len = snprintf(buf, PAGE_SIZE, "%lu\n", device->default_expires);
11827c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	dasd_put_device(device);
11837c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	return len;
11847c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland}
11857c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland
11867c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberlandstatic ssize_t
11877c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberlanddasd_expires_store(struct device *dev, struct device_attribute *attr,
11887c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	       const char *buf, size_t count)
11897c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland{
11907c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	struct dasd_device *device;
11917c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	unsigned long val;
11927c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland
11937c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	device = dasd_device_from_cdev(to_ccwdev(dev));
11947c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	if (IS_ERR(device))
11957c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland		return -ENODEV;
11967c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland
11977c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	if ((strict_strtoul(buf, 10, &val) != 0) ||
11987c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	    (val > DASD_EXPIRES_MAX) || val == 0) {
11997c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland		dasd_put_device(device);
12007c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland		return -EINVAL;
12017c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	}
12027c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland
12037c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	if (val)
12047c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland		device->default_expires = val;
12057c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland
12067c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	dasd_put_device(device);
12077c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	return count;
12087c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland}
12097c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland
12107c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberlandstatic DEVICE_ATTR(expires, 0644, dasd_expires_show, dasd_expires_store);
12117c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland
12125a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuberstatic ssize_t dasd_reservation_policy_show(struct device *dev,
12135a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber					    struct device_attribute *attr,
12145a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber					    char *buf)
12155a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber{
12165a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	struct dasd_devmap *devmap;
12175a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	int rc = 0;
12185a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
12195a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	devmap = dasd_find_busid(dev_name(dev));
12205a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	if (IS_ERR(devmap)) {
12215a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		rc = snprintf(buf, PAGE_SIZE, "ignore\n");
12225a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	} else {
12235a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		spin_lock(&dasd_devmap_lock);
12245a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		if (devmap->features & DASD_FEATURE_FAILONSLCK)
12255a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber			rc = snprintf(buf, PAGE_SIZE, "fail\n");
12265a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		else
12275a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber			rc = snprintf(buf, PAGE_SIZE, "ignore\n");
12285a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		spin_unlock(&dasd_devmap_lock);
12295a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	}
12305a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	return rc;
12315a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber}
12325a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
12335a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuberstatic ssize_t dasd_reservation_policy_store(struct device *dev,
12345a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber					     struct device_attribute *attr,
12355a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber					     const char *buf, size_t count)
12365a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber{
12375a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	struct dasd_devmap *devmap;
12385a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	int rc;
12395a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
12405a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
12415a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	if (IS_ERR(devmap))
12425a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		return PTR_ERR(devmap);
12435a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	rc = 0;
12445a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	spin_lock(&dasd_devmap_lock);
12455a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	if (sysfs_streq("ignore", buf))
12465a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		devmap->features &= ~DASD_FEATURE_FAILONSLCK;
12475a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	else if (sysfs_streq("fail", buf))
12485a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		devmap->features |= DASD_FEATURE_FAILONSLCK;
12495a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	else
12505a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		rc = -EINVAL;
12515a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	if (devmap->device)
12525a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		devmap->device->features = devmap->features;
12535a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	spin_unlock(&dasd_devmap_lock);
12545a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	if (rc)
12555a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		return rc;
12565a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	else
12575a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		return count;
12585a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber}
12595a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
12605a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuberstatic DEVICE_ATTR(reservation_policy, 0644,
12615a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		   dasd_reservation_policy_show, dasd_reservation_policy_store);
12625a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
12635a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuberstatic ssize_t dasd_reservation_state_show(struct device *dev,
12645a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber					   struct device_attribute *attr,
12655a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber					   char *buf)
12665a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber{
12675a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	struct dasd_device *device;
12685a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	int rc = 0;
12695a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
12705a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	device = dasd_device_from_cdev(to_ccwdev(dev));
12715a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	if (IS_ERR(device))
12725a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		return snprintf(buf, PAGE_SIZE, "none\n");
12735a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
12745a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	if (test_bit(DASD_FLAG_IS_RESERVED, &device->flags))
12755a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		rc = snprintf(buf, PAGE_SIZE, "reserved\n");
12765a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	else if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags))
12775a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		rc = snprintf(buf, PAGE_SIZE, "lost\n");
12785a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	else
12795a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		rc = snprintf(buf, PAGE_SIZE, "none\n");
12805a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	dasd_put_device(device);
12815a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	return rc;
12825a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber}
12835a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
12845a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuberstatic ssize_t dasd_reservation_state_store(struct device *dev,
12855a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber					    struct device_attribute *attr,
12865a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber					    const char *buf, size_t count)
12875a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber{
12885a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	struct dasd_device *device;
12895a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	int rc = 0;
12905a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
12915a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	device = dasd_device_from_cdev(to_ccwdev(dev));
12925a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	if (IS_ERR(device))
12935a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		return -ENODEV;
12945a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	if (sysfs_streq("reset", buf))
12955a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		clear_bit(DASD_FLAG_LOCK_STOLEN, &device->flags);
12965a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	else
12975a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		rc = -EINVAL;
12985a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	dasd_put_device(device);
12995a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
13005a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	if (rc)
13015a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		return rc;
13025a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	else
13035a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		return count;
13045a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber}
13055a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
13065a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuberstatic DEVICE_ATTR(last_known_reservation_state, 0644,
13075a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber		   dasd_reservation_state_show, dasd_reservation_state_store);
13085a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct attribute * dasd_attrs[] = {
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&dev_attr_readonly.attr,
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&dev_attr_discipline.attr,
13124dfd5c4593e69e9d399dd9e01d184dc534408f7eHorst Hummel	&dev_attr_status.attr,
13133d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	&dev_attr_alias.attr,
13143d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	&dev_attr_vendor.attr,
13153d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel	&dev_attr_uid.attr,
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&dev_attr_use_diag.attr,
1317e4dbb0f2b5dd6a836d0e5c60aa5f573e0bbcf76aStefan Haberland	&dev_attr_raw_track_access.attr,
131820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber	&dev_attr_eer_enabled.attr,
13199575bf265711cabe7147a68003a56a9f19f034daHorst Hummel	&dev_attr_erplog.attr,
132013de227bcd80fbdaeebe1f31154487dddb7d5b1eHolger Smolinski	&dev_attr_failfast.attr,
13217c8faa86290c1a2607d6b768a0b874ec392a5c2aStefan Haberland	&dev_attr_expires.attr,
13225a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	&dev_attr_reservation_policy.attr,
13235a27e60dec59a95bd7f8ae9a19ae2ede4f76395bStefan Weinhuber	&dev_attr_last_known_reservation_state.attr,
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NULL,
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct attribute_group dasd_attr_group = {
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.attrs = dasd_attrs,
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel/*
1332f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel * Return value of the specified feature.
1333f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel */
1334f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummelint
1335f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummeldasd_get_feature(struct ccw_device *cdev, int feature)
1336f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel{
1337f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	struct dasd_devmap *devmap;
1338f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
13392a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers	devmap = dasd_find_busid(dev_name(&cdev->dev));
1340f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	if (IS_ERR(devmap))
1341405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel		return PTR_ERR(devmap);
1342f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
1343f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	return ((devmap->features & feature) != 0);
1344f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel}
1345f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
1346f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel/*
1347f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel * Set / reset given feature.
1348f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel * Flag indicates wether to set (!=0) or the reset (=0) the feature.
1349f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel */
1350f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummelint
1351f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummeldasd_set_feature(struct ccw_device *cdev, int feature, int flag)
1352f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel{
1353f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	struct dasd_devmap *devmap;
1354f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
13552a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers	devmap = dasd_find_busid(dev_name(&cdev->dev));
1356f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	if (IS_ERR(devmap))
1357405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel		return PTR_ERR(devmap);
1358f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
1359f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	spin_lock(&dasd_devmap_lock);
1360f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	if (flag)
1361f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel		devmap->features |= feature;
1362f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	else
1363f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel		devmap->features &= ~feature;
1364c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel	if (devmap->device)
1365c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel		devmap->device->features = devmap->features;
1366f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	spin_unlock(&dasd_devmap_lock);
1367f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel	return 0;
1368f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel}
1369f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
1370f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_add_sysfs_files(struct ccw_device *cdev)
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_remove_sysfs_files(struct ccw_device *cdev)
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_devmap_init(void)
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize devmap structures. */
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dasd_max_devindex = 0;
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 256; i++)
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		INIT_LIST_HEAD(&dasd_hashlists[i]);
1393405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel	return 0;
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_devmap_exit(void)
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dasd_forget_ranges();
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1401