dasd_devmap.c revision a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6e
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> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is ugly... */ 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PRINTK_HEADER "dasd_devmap:" 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "dasd_int.h" 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldskmem_cache_t *dasd_page_cache; 29405455734e1cdec09c37233216f9240cb1a058e5Horst HummelEXPORT_SYMBOL_GPL(dasd_page_cache); 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dasd_devmap_t is used to store the features and the relation 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * between device number and device index. To find a dasd_devmap_t 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that corresponds to a device number of a device index each 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dasd_devmap_t is added to two linked lists, one to search by 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the device number and one to search by the device index. As 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * soon as big minor numbers are available the device index list 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can be removed since the device number will then be identical 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the device index. 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_devmap { 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head list; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char bus_id[BUS_ID_SIZE]; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int devindex; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short features; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_device *device; 473d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel struct dasd_uid uid; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 51b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter * dasd_server_ssid_map contains a globally unique storage server subsystem ID. 52b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter * dasd_server_ssid_list contains the list of all subsystem IDs accessed by 53b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter * the DASD device driver. 54405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel */ 55b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiterstruct dasd_server_ssid_map { 56405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel struct list_head list; 578e79a441a4d8a34d64efe93add49b3eefca5cd1cHorst Hummel struct system_id { 58405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel char vendor[4]; 59405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel char serial[15]; 608e79a441a4d8a34d64efe93add49b3eefca5cd1cHorst Hummel __u16 ssid; 61405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel } sid; 62405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel}; 63405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel 64b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiterstatic struct list_head dasd_server_ssid_list; 65405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel 66405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel/* 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Parameter parsing functions for dasd= parameter. The syntax is: 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <devno> : (0x)?[0-9a-fA-F]+ 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <busid> : [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+ 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <feature> : ro 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <feature_list> : \(<feature>(:<feature>)*\) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <devno-range> : <devno>(-<devno>)?<feature_list>? 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <busid-range> : <busid>(-<busid>)?<feature_list>? 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <devices> : <devno-range>|<busid-range> 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <dasd_module> : dasd_diag_mod|dasd_eckd_mod|dasd_fba_mod 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <dasd> : autodetect|probeonly|<devices>(,<devices>)* 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dasd_probeonly = 0; /* is true, when probeonly mode is active */ 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dasd_autodetect = 0; /* is true, when autodetection is active */ 82405455734e1cdec09c37233216f9240cb1a058e5Horst Hummelint dasd_nopav = 0; /* is true, when PAV is disabled */ 83405455734e1cdec09c37233216f9240cb1a058e5Horst HummelEXPORT_SYMBOL_GPL(dasd_nopav); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * char *dasd[] is intended to hold the ranges supplied by the dasd= statement 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it is named 'dasd' to directly be filled by insmod with the comma separated 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * strings when running as a module. 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *dasd[256]; 918d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param_array(dasd, charp, NULL, 0); 928d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russell 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 94d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel * Single spinlock to protect devmap and servermap structures and lists. 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(dasd_devmap_lock); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Hash lists for devmap structures. 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct list_head dasd_hashlists[256]; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dasd_max_devindex; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dasd_devmap *dasd_add_busid(char *, int); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_hash_busid(char *bus_id) 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hash, i; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hash = 0; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; (i < BUS_ID_SIZE) && *bus_id; i++, bus_id++) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hash += *bus_id; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return hash & 0xff; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef MODULE 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The parameter parsing functions for builtin-drivers are called 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * before kmalloc works. Store the pointers to the parameters strings 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * into dasd[] for later processing. 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_call_setup(char *str) 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int count = 0; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count < 256) 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dasd[count++] = str; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__setup ("dasd=", dasd_call_setup); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* #ifndef MODULE */ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read a device busid/devno from a string. 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_busid(char **str, int *id0, int *id1, int *devno) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val, old_style; 143138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check for leading '0x' */ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_style = 0; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((*str)[0] == '0' && (*str)[1] == 'x') { 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *str += 2; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_style = 1; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!isxdigit((*str)[0])) /* We require at least one hex digit */ 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = simple_strtoul(*str, str, 16); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_style || (*str)[0] != '.') { 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *id0 = *id1 = 0; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val < 0 || val > 0xffff) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *devno = val; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* New style x.y.z busid */ 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val < 0 || val > 0xff) 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *id0 = val; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*str)++; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!isxdigit((*str)[0])) /* We require at least one hex digit */ 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = simple_strtoul(*str, str, 16); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val < 0 || val > 0xff || (*str)++[0] != '.') 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *id1 = val; 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 > 0xffff) 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *devno = val; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read colon separated list of dasd features. Currently there is 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * only one: "ro" for read-only devices. The default feature set 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is empty (value 0). 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_feature_list(char *str, char **endp) 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int features, len, rc; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = 0; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*str != '(') { 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *endp = str; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return DASD_FEATURE_DEFAULT; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str++; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds features = 0; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (1) { 199138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel for (len = 0; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str[len] && str[len] != ':' && str[len] != ')'; len++); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len == 2 && !strncmp(str, "ro", 2)) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds features |= DASD_FEATURE_READONLY; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (len == 4 && !strncmp(str, "diag", 4)) 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds features |= DASD_FEATURE_USEDIAG; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MESSAGE(KERN_WARNING, 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unsupported feature: %*s, " 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ignoring setting", len, str); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -EINVAL; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str += len; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*str != ':') 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str++; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*str != ')') { 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MESSAGE(KERN_WARNING, "%s", 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "missing ')' in dasd parameter string\n"); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -EINVAL; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str++; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *endp = str; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc != 0) 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return features; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try to match the first element on the comma separated parse string 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with one of the known keywords. If a keyword is found, take the approprate 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * action and return a pointer to the residual string. If the first element 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * could not be matched to any keyword then return an error code. 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char * 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse_keyword( char *parsestring ) { 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *nextcomma, *residual_str; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int length; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nextcomma = strchr(parsestring,','); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nextcomma) { 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds length = nextcomma - parsestring; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds residual_str = nextcomma + 1; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds length = strlen(parsestring); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds residual_str = parsestring + length; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 248405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel if (strncmp("autodetect", parsestring, length) == 0) { 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dasd_autodetect = 1; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MESSAGE (KERN_INFO, "%s", 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "turning to autodetection mode"); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return residual_str; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 254405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel if (strncmp("probeonly", parsestring, length) == 0) { 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dasd_probeonly = 1; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MESSAGE(KERN_INFO, "%s", 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "turning to probeonly mode"); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return residual_str; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 260405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel if (strncmp("nopav", parsestring, length) == 0) { 261405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel dasd_nopav = 1; 262405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel MESSAGE(KERN_INFO, "%s", "disable PAV mode"); 263405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel return residual_str; 264405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel } 265405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel if (strncmp("fixedbuffers", parsestring, length) == 0) { 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dasd_page_cache) 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return residual_str; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dasd_page_cache = 2692f6c55fc3109bcfa1bb1a112c825e07212c20f37Heiko Carstens kmem_cache_create("dasd_page_cache", PAGE_SIZE, 2702f6c55fc3109bcfa1bb1a112c825e07212c20f37Heiko Carstens PAGE_SIZE, SLAB_CACHE_DMA, 2712f6c55fc3109bcfa1bb1a112c825e07212c20f37Heiko Carstens NULL, NULL ); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dasd_page_cache) 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MESSAGE(KERN_WARNING, "%s", "Failed to create slab, " 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fixed buffer mode disabled."); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MESSAGE (KERN_INFO, "%s", 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "turning on fixed buffer mode"); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return residual_str; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EINVAL); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try to interprete the first element on the comma separated parse string 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as a device number or a range of devices. If the interpretation is 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * successfull, create the matching dasd_devmap entries and return a pointer 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the residual string. 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If interpretation fails or in case of an error, return an error code. 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char * 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse_range( char *parsestring ) { 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int from, from_id0, from_id1; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int to, to_id0, to_id1; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int features, rc; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char bus_id[BUS_ID_SIZE+1], *str; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str = parsestring; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = dasd_busid(&str, &from_id0, &from_id1, &from); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc == 0) { 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to = from; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to_id0 = from_id0; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to_id1 = from_id1; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*str == '-') { 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str++; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = dasd_busid(&str, &to_id0, &to_id1, &to); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc == 0 && 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (from_id0 != to_id0 || from_id1 != to_id1 || from > to)) 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -EINVAL; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MESSAGE(KERN_ERR, "Invalid device range %s", parsestring); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(rc); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds features = dasd_feature_list(str, &str); 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (features < 0) 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EINVAL); 320405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel /* each device in dasd= parameter should be set initially online */ 321405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel features |= DASD_FEATURE_INITIAL_ONLINE; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (from <= to) { 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(bus_id, "%01x.%01x.%04x", 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds from_id0, from_id1, from++); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = dasd_add_busid(bus_id, features); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(devmap)) 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (char *)devmap; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*str == ',') 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return str + 1; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*str == '\0') 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return str; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MESSAGE(KERN_WARNING, 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "junk at end of dasd parameter string: %s\n", str); 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EINVAL); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline char * 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse_next_element( char *parsestring ) { 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char * residual_str; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds residual_str = dasd_parse_keyword(parsestring); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!IS_ERR(residual_str)) 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return residual_str; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds residual_str = dasd_parse_range(parsestring); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return residual_str; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Parse parameters stored in dasd[] 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The 'dasd=...' parameter allows to specify a comma separated list of 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * keywords and device ranges. When the dasd driver is build into the kernel, 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the complete list will be stored as one element of the dasd[] array. 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When the dasd driver is build as a module, then the list is broken into 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it's elements and each dasd[] entry contains one element. 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_parse(void) 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc, i; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *parsestring; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = 0; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 256; i++) { 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dasd[i] == NULL) 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parsestring = dasd[i]; 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* loop over the comma separated list in the parsestring */ 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (*parsestring) { 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parsestring = dasd_parse_next_element(parsestring); 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(IS_ERR(parsestring)) { 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = PTR_ERR(parsestring); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBF_EVENT(DBF_ALERT, "%s", "invalid range found"); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Add a devmap for the device specified by busid. It is possible that 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the devmap already exists (dasd= parameter). The order of the devices 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * added through this function will define the kdevs for the individual 387138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel * devices. 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dasd_devmap * 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_add_busid(char *bus_id, int features) 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap, *new, *tmp; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hash; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new = (struct dasd_devmap *) 396138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!new) 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOMEM); 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&dasd_devmap_lock); 400d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens devmap = NULL; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hash = dasd_hash_busid(bus_id); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(tmp, &dasd_hashlists[hash], list) 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) { 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = tmp; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!devmap) { 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This bus_id is new. */ 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new->devindex = dasd_max_devindex++; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strncpy(new->bus_id, bus_id, BUS_ID_SIZE); 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new->features = features; 412d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens new->device = NULL; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add(&new->list, &dasd_hashlists[hash]); 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = new; 415d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens new = NULL; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&dasd_devmap_lock); 41817fd682e544556a2a829e94383239c029bb21c5eJesper Juhl kfree(new); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return devmap; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find devmap for device with given bus_id. 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dasd_devmap * 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_find_busid(char *bus_id) 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap, *tmp; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hash; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&dasd_devmap_lock); 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = ERR_PTR(-ENODEV); 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hash = dasd_hash_busid(bus_id); 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(tmp, &dasd_hashlists[hash], list) { 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) { 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = tmp; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&dasd_devmap_lock); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return devmap; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check if busid has been added to the list of dasd ranges. 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_busid_known(char *bus_id) 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Forget all about the device numbers added so far. 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This may only be called at module unload or system shutdown. 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_forget_ranges(void) 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap, *n; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&dasd_devmap_lock); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 256; i++) { 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) { 466606f44228e257ea1e35557c2fec7133cca634096Eric Sesterhenn BUG_ON(devmap->device != NULL); 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&devmap->list); 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(devmap); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&dasd_devmap_lock); 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find the device struct by its device index. 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_device * 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_device_from_devindex(int devindex) 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap, *tmp; 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_device *device; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&dasd_devmap_lock); 485d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens devmap = NULL; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; (i < 256) && !devmap; i++) 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(tmp, &dasd_hashlists[i], list) 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp->devindex == devindex) { 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Found the devmap for the device. */ 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = tmp; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (devmap && devmap->device) { 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device = devmap->device; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dasd_get_device(device); 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device = ERR_PTR(-ENODEV); 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&dasd_devmap_lock); 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return device; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return devmap for cdev. If no devmap exists yet, create one and 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * connect it to the cdev. 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dasd_devmap * 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_devmap_from_cdev(struct ccw_device *cdev) 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = dasd_find_busid(cdev->dev.bus_id); 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(devmap)) 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = dasd_add_busid(cdev->dev.bus_id, 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DASD_FEATURE_DEFAULT); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return devmap; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Create a dasd device structure for cdev. 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_device * 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_create_device(struct ccw_device *cdev) 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_device *device; 526a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky unsigned long flags; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = dasd_devmap_from_cdev(cdev); 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(devmap)) 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (void *) devmap; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device = dasd_alloc_device(); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(device)) 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return device; 536a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky atomic_set(&device->ref_count, 3); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&dasd_devmap_lock); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!devmap->device) { 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap->device = device; 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device->devindex = devmap->devindex; 542c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel device->features = devmap->features; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_device(&cdev->dev); 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device->cdev = cdev; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = 0; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Someone else was faster. */ 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -EBUSY; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&dasd_devmap_lock); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dasd_free_device(device); 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(rc); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 555a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky 556a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky spin_lock_irqsave(get_ccwdev_lock(cdev), flags); 557a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky cdev->dev.driver_data = device; 558a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); 559a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return device; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wait queue for dasd_delete_device waits. 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Remove a dasd device structure. The passed referenced 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is destroyed. 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_delete_device(struct dasd_device *device) 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ccw_device *cdev; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap; 577a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky unsigned long flags; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* First remove device pointer from devmap. */ 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = dasd_find_busid(device->cdev->dev.bus_id); 581606f44228e257ea1e35557c2fec7133cca634096Eric Sesterhenn BUG_ON(IS_ERR(devmap)); 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&dasd_devmap_lock); 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (devmap->device != device) { 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&dasd_devmap_lock); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dasd_put_device(device); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap->device = NULL; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&dasd_devmap_lock); 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky /* Disconnect dasd_device structure from ccw_device structure. */ 592a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); 593a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky device->cdev->dev.driver_data = NULL; 594a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); 595a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky 596a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky /* 597a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky * Drop ref_count by 3, one for the devmap reference, one for 598a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky * the cdev reference and one for the passed reference. 599a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky */ 600a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky atomic_sub(3, &device->ref_count); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Wait for reference counter to drop to zero. */ 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Disconnect dasd_device structure from ccw_device structure. */ 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cdev = device->cdev; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device->cdev = NULL; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Put ccw_device structure. */ 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_device(&cdev->dev); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now the device structure can be freed. */ 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dasd_free_device(device); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reference counter dropped to zero. Wake up waiter 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in dasd_delete_device. 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_put_device_wake(struct dasd_device *device) 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up(&dasd_delete_wq); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return dasd_device structure associated with cdev. 628a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky * This function needs to be called with the ccw device 629a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky * lock held. It can be used from interrupt context. 630a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky */ 631a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefskystruct dasd_device * 632a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefskydasd_device_from_cdev_locked(struct ccw_device *cdev) 633a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky{ 634a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky struct dasd_device *device = cdev->dev.driver_data; 635a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky 636a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky if (!device) 637a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky return ERR_PTR(-ENODEV); 638a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky dasd_get_device(device); 639a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky return device; 640a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky} 641a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky 642a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky/* 643a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky * Return dasd_device structure associated with cdev. 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dasd_device * 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_device_from_cdev(struct ccw_device *cdev) 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_device *device; 649a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky unsigned long flags; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky spin_lock_irqsave(get_ccwdev_lock(cdev), flags); 652a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky device = dasd_device_from_cdev_locked(cdev); 653a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return device; 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SECTION: files in sysfs 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * readonly controls the readonly status of a dasd 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 665e404e274f62665f3333d6a539d0d3701f678a598Yani Ioannoudasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf) 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ro_flag; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = dasd_find_busid(dev->bus_id); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!IS_ERR(devmap)) 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0; 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0; 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n"); 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 679138c014dcba74211dc4e835658f34a787c40cf17Horst Hummeldasd_ro_store(struct device *dev, struct device_attribute *attr, 680138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel const char *buf, size_t count) 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap; 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ro_flag; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(devmap)) 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(devmap); 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ro_flag = buf[0] == '1'; 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&dasd_devmap_lock); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ro_flag) 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap->features |= DASD_FEATURE_READONLY; 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap->features &= ~DASD_FEATURE_READONLY; 694c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel if (devmap->device) 695c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel devmap->device->features = devmap->features; 696f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel if (devmap->device && devmap->device->gdp) 697f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel set_disk_ro(devmap->device->gdp, ro_flag); 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&dasd_devmap_lock); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store); 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * use_diag controls whether the driver should use diag rather than ssch 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to talk to the device 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 708138c014dcba74211dc4e835658f34a787c40cf17Horst Hummelstatic ssize_t 709e404e274f62665f3333d6a539d0d3701f678a598Yani Ioannoudasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf) 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap; 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int use_diag; 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = dasd_find_busid(dev->bus_id); 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!IS_ERR(devmap)) 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0; 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0; 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, use_diag ? "1\n" : "0\n"); 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 723138c014dcba74211dc4e835658f34a787c40cf17Horst Hummeldasd_use_diag_store(struct device *dev, struct device_attribute *attr, 724138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel const char *buf, size_t count) 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dasd_devmap *devmap; 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ssize_t rc; 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int use_diag; 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(devmap)) 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(devmap); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds use_diag = buf[0] == '1'; 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&dasd_devmap_lock); 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Changing diag discipline flag is only allowed in offline state. */ 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = count; 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!devmap->device) { 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (use_diag) 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap->features |= DASD_FEATURE_USEDIAG; 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devmap->features &= ~DASD_FEATURE_USEDIAG; 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -EPERM; 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&dasd_devmap_lock); 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 748138c014dcba74211dc4e835658f34a787c40cf17Horst Hummelstatic DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store); 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 751138c014dcba74211dc4e835658f34a787c40cf17Horst Hummeldasd_discipline_show(struct device *dev, struct device_attribute *attr, 752138c014dcba74211dc4e835658f34a787c40cf17Horst Hummel char *buf) 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 754a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky struct dasd_device *device; 755a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky ssize_t len; 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 757a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky device = dasd_device_from_cdev(to_ccwdev(dev)); 758a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky if (!IS_ERR(device) && device->discipline) { 759a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky len = snprintf(buf, PAGE_SIZE, "%s\n", 760a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky device->discipline->name); 761a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky dasd_put_device(device); 762a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky } else 763a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky len = snprintf(buf, PAGE_SIZE, "none\n"); 764a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6eMartin Schwidefsky return len; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL); 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7693d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic ssize_t 7703d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummeldasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf) 7713d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{ 7723d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel struct dasd_devmap *devmap; 7733d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel int alias; 7743d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 7753d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel devmap = dasd_find_busid(dev->bus_id); 7763d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel spin_lock(&dasd_devmap_lock); 7773d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel if (!IS_ERR(devmap)) 7783d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel alias = devmap->uid.alias; 7793d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel else 7803d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel alias = 0; 7813d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel spin_unlock(&dasd_devmap_lock); 7823d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 7833d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel return sprintf(buf, alias ? "1\n" : "0\n"); 7843d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel} 7853d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 7863d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL); 7873d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 7883d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic ssize_t 7893d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummeldasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) 7903d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{ 7913d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel struct dasd_devmap *devmap; 7923d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel char *vendor; 7933d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 7943d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel devmap = dasd_find_busid(dev->bus_id); 7953d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel spin_lock(&dasd_devmap_lock); 7963d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) 7973d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel vendor = devmap->uid.vendor; 7983d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel else 7993d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel vendor = ""; 8003d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel spin_unlock(&dasd_devmap_lock); 8013d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 8023d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel return snprintf(buf, PAGE_SIZE, "%s\n", vendor); 8033d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel} 8043d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 8053d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL); 8063d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 8073d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel#define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial */ 14 + 1 +\ 8083d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel /* SSID */ 4 + 1 + /* unit addr */ 2 + 1) 8093d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 8103d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic ssize_t 8113d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummeldasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf) 8123d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{ 8133d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel struct dasd_devmap *devmap; 8143d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel char uid[UID_STRLEN]; 8153d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 8163d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel devmap = dasd_find_busid(dev->bus_id); 8173d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel spin_lock(&dasd_devmap_lock); 8183d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) 8193d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x", 8203d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel devmap->uid.vendor, devmap->uid.serial, 8213d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel devmap->uid.ssid, devmap->uid.unit_addr); 8223d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel else 8233d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel uid[0] = 0; 8243d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel spin_unlock(&dasd_devmap_lock); 8253d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 8263d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel return snprintf(buf, PAGE_SIZE, "%s\n", uid); 8273d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel} 8283d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 8293d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelstatic DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL); 8303d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 83120c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber/* 83220c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber * extended error-reporting 83320c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber */ 83420c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberstatic ssize_t 83520c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberdasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf) 83620c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber{ 83720c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber struct dasd_devmap *devmap; 83820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber int eer_flag; 83920c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber 84020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber devmap = dasd_find_busid(dev->bus_id); 84120c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber if (!IS_ERR(devmap) && devmap->device) 84220c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber eer_flag = dasd_eer_enabled(devmap->device); 84320c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber else 84420c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber eer_flag = 0; 84520c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n"); 84620c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber} 84720c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber 84820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberstatic ssize_t 84920c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberdasd_eer_store(struct device *dev, struct device_attribute *attr, 85020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber const char *buf, size_t count) 85120c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber{ 85220c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber struct dasd_devmap *devmap; 85320c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber int rc; 85420c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber 85520c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); 85620c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber if (IS_ERR(devmap)) 85720c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber return PTR_ERR(devmap); 85820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber if (!devmap->device) 85920c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber return count; 86020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber if (buf[0] == '1') { 86120c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber rc = dasd_eer_enable(devmap->device); 86220c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber if (rc) 86320c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber return rc; 86420c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber } else 86520c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber dasd_eer_disable(devmap->device); 86620c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber return count; 86720c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber} 86820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber 86920c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuberstatic DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store); 87020c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct attribute * dasd_attrs[] = { 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &dev_attr_readonly.attr, 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &dev_attr_discipline.attr, 8743d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel &dev_attr_alias.attr, 8753d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel &dev_attr_vendor.attr, 8763d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel &dev_attr_uid.attr, 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &dev_attr_use_diag.attr, 87820c644680af1ef9a6b36c0873f59498c98b07ab1Stefan Weinhuber &dev_attr_eer_enabled.attr, 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL, 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct attribute_group dasd_attr_group = { 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attrs = dasd_attrs, 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 886405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel/* 8873d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel * Return copy of the device unique identifier. 8883d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel */ 8893d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelint 8903d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummeldasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) 8913d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{ 8923d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel struct dasd_devmap *devmap; 8933d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 8943d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel devmap = dasd_find_busid(cdev->dev.bus_id); 8953d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel if (IS_ERR(devmap)) 8963d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel return PTR_ERR(devmap); 8973d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel spin_lock(&dasd_devmap_lock); 8983d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel *uid = devmap->uid; 8993d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel spin_unlock(&dasd_devmap_lock); 9003d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel return 0; 9013d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel} 9023d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 9033d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel/* 9043d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel * Register the given device unique identifier into devmap struct. 905b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter * In addition check if the related storage server subsystem ID is already 906b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter * contained in the dasd_server_ssid_list. If subsystem ID is not contained, 907b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter * create new entry. 908405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel * Return 0 if server was already in serverlist, 909405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel * 1 if the server was added successful 910405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel * <0 in case of error. 9113d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel */ 9123d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummelint 9133d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummeldasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) 9143d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel{ 9153d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel struct dasd_devmap *devmap; 916b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter struct dasd_server_ssid_map *srv, *tmp; 9173d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 9183d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel devmap = dasd_find_busid(cdev->dev.bus_id); 9193d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel if (IS_ERR(devmap)) 9203d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel return PTR_ERR(devmap); 921d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel 922b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter /* generate entry for server_ssid_map */ 923b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter srv = (struct dasd_server_ssid_map *) 924b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter kzalloc(sizeof(struct dasd_server_ssid_map), GFP_KERNEL); 925d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel if (!srv) 926d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel return -ENOMEM; 927d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1); 928d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1); 9298e79a441a4d8a34d64efe93add49b3eefca5cd1cHorst Hummel srv->sid.ssid = uid->ssid; 930d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel 931d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel /* server is already contained ? */ 9323d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel spin_lock(&dasd_devmap_lock); 9333d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel devmap->uid = *uid; 934b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter list_for_each_entry(tmp, &dasd_server_ssid_list, list) { 935d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel if (!memcmp(&srv->sid, &tmp->sid, 9368e79a441a4d8a34d64efe93add49b3eefca5cd1cHorst Hummel sizeof(struct system_id))) { 937d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel kfree(srv); 938d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel srv = NULL; 939d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel break; 940d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel } 941d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel } 942d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel 943d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel /* add servermap to serverlist */ 944d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel if (srv) 945b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter list_add(&srv->list, &dasd_server_ssid_list); 9463d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel spin_unlock(&dasd_devmap_lock); 947d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel 948d0710c7c9eea2145a0614f39dbe9dc8cb4ae14daHorst Hummel return (srv ? 1 : 0); 9493d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel} 950405455734e1cdec09c37233216f9240cb1a058e5Horst HummelEXPORT_SYMBOL_GPL(dasd_set_uid); 9513d052595423b4432f4d599c1aeb1949ac0da7314Horst Hummel 952f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel/* 953f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel * Return value of the specified feature. 954f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel */ 955f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummelint 956f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummeldasd_get_feature(struct ccw_device *cdev, int feature) 957f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel{ 958f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel struct dasd_devmap *devmap; 959f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel 960f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel devmap = dasd_find_busid(cdev->dev.bus_id); 961f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel if (IS_ERR(devmap)) 962405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel return PTR_ERR(devmap); 963f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel 964f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel return ((devmap->features & feature) != 0); 965f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel} 966f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel 967f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel/* 968f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel * Set / reset given feature. 969f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel * Flag indicates wether to set (!=0) or the reset (=0) the feature. 970f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel */ 971f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummelint 972f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummeldasd_set_feature(struct ccw_device *cdev, int feature, int flag) 973f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel{ 974f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel struct dasd_devmap *devmap; 975f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel 976f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel devmap = dasd_find_busid(cdev->dev.bus_id); 977f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel if (IS_ERR(devmap)) 978405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel return PTR_ERR(devmap); 979f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel 980f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel spin_lock(&dasd_devmap_lock); 981f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel if (flag) 982f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel devmap->features |= feature; 983f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel else 984f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel devmap->features &= ~feature; 985c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel if (devmap->device) 986c6eb7b7703ac4b3401b74f411c8c51ded214bf19Horst Hummel devmap->device->features = devmap->features; 987f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel spin_unlock(&dasd_devmap_lock); 988f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel return 0; 989f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel} 990f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel 991f24acd4503270ed4c842c8fef0b71105285e0a06Horst Hummel 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_add_sysfs_files(struct ccw_device *cdev) 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group); 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_remove_sysfs_files(struct ccw_device *cdev) 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group); 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_devmap_init(void) 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize devmap structures. */ 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dasd_max_devindex = 0; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 256; i++) 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&dasd_hashlists[i]); 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1015405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel /* Initialize servermap structure. */ 1016b18a60e7c2a7f2a17dbd57885621a42d546e2f7dPeter Oberparleiter INIT_LIST_HEAD(&dasd_server_ssid_list); 1017405455734e1cdec09c37233216f9240cb1a058e5Horst Hummel return 0; 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdasd_devmap_exit(void) 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dasd_forget_ranges(); 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1025