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