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