^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Horst Hummel <Horst.Hummel@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Carsten Otte <Cotte@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Martin Schwidefsky <schwidefsky@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Bugreports.to..: <Linux390@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright IBM Corp. 1999,2001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Device mapping and dasd= parameter parsing functions. All devmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * functions may not be called from interrupt context. In particular
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * dasd_get_device is a no-no from interrupt context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define KMSG_COMPONENT "dasd"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/ipl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* This is ugly... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PRINTK_HEADER "dasd_devmap:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define DASD_BUS_ID_SIZE 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define DASD_MAX_PARAMS 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "dasd_int.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct kmem_cache *dasd_page_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) EXPORT_SYMBOL_GPL(dasd_page_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * dasd_devmap_t is used to store the features and the relation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * between device number and device index. To find a dasd_devmap_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * that corresponds to a device number of a device index each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * dasd_devmap_t is added to two linked lists, one to search by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * the device number and one to search by the device index. As
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * soon as big minor numbers are available the device index list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * can be removed since the device number will then be identical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * to the device index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct dasd_devmap {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) char bus_id[DASD_BUS_ID_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned int devindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned short features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Parameter parsing functions for dasd= parameter. The syntax is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * <devno> : (0x)?[0-9a-fA-F]+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * <busid> : [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * <feature> : ro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * <feature_list> : \(<feature>(:<feature>)*\)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * <devno-range> : <devno>(-<devno>)?<feature_list>?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * <busid-range> : <busid>(-<busid>)?<feature_list>?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * <devices> : <devno-range>|<busid-range>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * <dasd_module> : dasd_diag_mod|dasd_eckd_mod|dasd_fba_mod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * <dasd> : autodetect|probeonly|<devices>(,<devices>)*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int dasd_probeonly = 0; /* is true, when probeonly mode is active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int dasd_autodetect = 0; /* is true, when autodetection is active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int dasd_nopav = 0; /* is true, when PAV is disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) EXPORT_SYMBOL_GPL(dasd_nopav);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int dasd_nofcx; /* disable High Performance Ficon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) EXPORT_SYMBOL_GPL(dasd_nofcx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * char *dasd[] is intended to hold the ranges supplied by the dasd= statement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * it is named 'dasd' to directly be filled by insmod with the comma separated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * strings when running as a module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static char *dasd[DASD_MAX_PARAMS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) module_param_array(dasd, charp, NULL, S_IRUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * Single spinlock to protect devmap and servermap structures and lists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static DEFINE_SPINLOCK(dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * Hash lists for devmap structures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static struct list_head dasd_hashlists[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int dasd_max_devindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static struct dasd_devmap *dasd_add_busid(const char *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) dasd_hash_busid(const char *bus_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int hash, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) hash = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) for (i = 0; (i < DASD_BUS_ID_SIZE) && *bus_id; i++, bus_id++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) hash += *bus_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return hash & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int __init dasd_call_setup(char *opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int i __initdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) char *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) while (i < DASD_MAX_PARAMS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) tmp = strsep(&opt, ",");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (!tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) dasd[i++] = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) __setup ("dasd=", dasd_call_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #endif /* #ifndef MODULE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define DASD_IPLDEV "ipldev"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * Read a device busid/devno from a string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int __init dasd_busid(char *str, int *id0, int *id1, int *devno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) char *tok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Interpret ipldev busid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (strncmp(DASD_IPLDEV, str, strlen(DASD_IPLDEV)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (ipl_info.type != IPL_TYPE_CCW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) pr_err("The IPL device is not a CCW device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) *id0 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) *id1 = ipl_info.data.ccw.dev_id.ssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *devno = ipl_info.data.ccw.dev_id.devno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* Old style 0xXXXX or XXXX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (!kstrtouint(str, 16, &val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) *id0 = *id1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (val > 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) *devno = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* New style x.y.z busid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) tok = strsep(&str, ".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (kstrtouint(tok, 16, &val) || val > 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) *id0 = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) tok = strsep(&str, ".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (kstrtouint(tok, 16, &val) || val > 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *id1 = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) tok = strsep(&str, ".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (kstrtouint(tok, 16, &val) || val > 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) *devno = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * Read colon separated list of dasd features.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static int __init dasd_feature_list(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int features, len, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) features = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (!str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return DASD_FEATURE_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) for (len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) str[len] && str[len] != ':' && str[len] != ')'; len++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (len == 2 && !strncmp(str, "ro", 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) features |= DASD_FEATURE_READONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) else if (len == 4 && !strncmp(str, "diag", 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) features |= DASD_FEATURE_USEDIAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) else if (len == 3 && !strncmp(str, "raw", 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) features |= DASD_FEATURE_USERAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) else if (len == 6 && !strncmp(str, "erplog", 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) features |= DASD_FEATURE_ERPLOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) else if (len == 8 && !strncmp(str, "failfast", 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) features |= DASD_FEATURE_FAILFAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) pr_warn("%.*s is not a supported device option\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) len, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) str += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (*str != ':')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return rc ? : features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * Try to match the first element on the comma separated parse string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * with one of the known keywords. If a keyword is found, take the approprate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * action and return a pointer to the residual string. If the first element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * could not be matched to any keyword then return an error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int __init dasd_parse_keyword(char *keyword)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int length = strlen(keyword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (strncmp("autodetect", keyword, length) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dasd_autodetect = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) pr_info("The autodetection mode has been activated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (strncmp("probeonly", keyword, length) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) dasd_probeonly = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) pr_info("The probeonly mode has been activated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (strncmp("nopav", keyword, length) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (MACHINE_IS_VM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) pr_info("'nopav' is not supported on z/VM\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) dasd_nopav = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) pr_info("PAV support has be deactivated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (strncmp("nofcx", keyword, length) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) dasd_nofcx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) pr_info("High Performance FICON support has been "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) "deactivated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (strncmp("fixedbuffers", keyword, length) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (dasd_page_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) dasd_page_cache =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) kmem_cache_create("dasd_page_cache", PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) PAGE_SIZE, SLAB_CACHE_DMA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (!dasd_page_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) DBF_EVENT(DBF_WARNING, "%s", "Failed to create slab, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) "fixed buffer mode disabled.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) DBF_EVENT(DBF_INFO, "%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) "turning on fixed buffer mode");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * Split a string of a device range into its pieces and return the from, to, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * feature parts separately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * e.g.:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * 0.0.1234-0.0.5678(ro:erplog) -> from: 0.0.1234 to: 0.0.5678 features: ro:erplog
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * 0.0.8765(raw) -> from: 0.0.8765 to: null features: raw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * 0x4321 -> from: 0x4321 to: null features: null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int __init dasd_evaluate_range_param(char *range, char **from_str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) char **to_str, char **features_str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* Do we have a range or a single device? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (strchr(range, '-')) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) *from_str = strsep(&range, "-");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) *to_str = strsep(&range, "(");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) *features_str = strsep(&range, ")");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) *from_str = strsep(&range, "(");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) *features_str = strsep(&range, ")");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (*features_str && !range) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) pr_warn("A closing parenthesis ')' is missing in the dasd= parameter\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * Try to interprete the range string as a device number or a range of devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * If the interpretation is successful, create the matching dasd_devmap entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * If interpretation fails or in case of an error, return an error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int __init dasd_parse_range(const char *range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int from, from_id0, from_id1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int to, to_id0, to_id1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) char bus_id[DASD_BUS_ID_SIZE + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) char *features_str = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) char *from_str = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) char *to_str = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) char *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) tmp = kstrdup(range, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (!tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (dasd_evaluate_range_param(tmp, &from_str, &to_str, &features_str)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (dasd_busid(from_str, &from_id0, &from_id1, &from)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) to = from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) to_id0 = from_id0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) to_id1 = from_id1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (to_str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (dasd_busid(to_str, &to_id0, &to_id1, &to)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (from_id0 != to_id0 || from_id1 != to_id1 || from > to) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) pr_err("%s is not a valid device range\n", range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) features = dasd_feature_list(features_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (features < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /* each device in dasd= parameter should be set initially online */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) features |= DASD_FEATURE_INITIAL_ONLINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) while (from <= to) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) sprintf(bus_id, "%01x.%01x.%04x", from_id0, from_id1, from++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) devmap = dasd_add_busid(bus_id, features);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (IS_ERR(devmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) rc = PTR_ERR(devmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) kfree(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * Parse parameters stored in dasd[]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * The 'dasd=...' parameter allows to specify a comma separated list of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * keywords and device ranges. The parameters in that list will be stored as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * separate elementes in dasd[].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) int __init dasd_parse(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int rc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) char *cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) for (i = 0; i < DASD_MAX_PARAMS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) cur = dasd[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (!cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (*cur == '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) rc = dasd_parse_keyword(cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) rc = dasd_parse_range(cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * Add a devmap for the device specified by busid. It is possible that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * the devmap already exists (dasd= parameter). The order of the devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * added through this function will define the kdevs for the individual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static struct dasd_devmap *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) dasd_add_busid(const char *bus_id, int features)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct dasd_devmap *devmap, *new, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) new = kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) devmap = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) hash = dasd_hash_busid(bus_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) list_for_each_entry(tmp, &dasd_hashlists[hash], list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (strncmp(tmp->bus_id, bus_id, DASD_BUS_ID_SIZE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) devmap = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!devmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* This bus_id is new. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) new->devindex = dasd_max_devindex++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) strlcpy(new->bus_id, bus_id, DASD_BUS_ID_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) new->features = features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) new->device = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) list_add(&new->list, &dasd_hashlists[hash]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) devmap = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) kfree(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * Find devmap for device with given bus_id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static struct dasd_devmap *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) dasd_find_busid(const char *bus_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct dasd_devmap *devmap, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) int hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) devmap = ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) hash = dasd_hash_busid(bus_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) list_for_each_entry(tmp, &dasd_hashlists[hash], list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (strncmp(tmp->bus_id, bus_id, DASD_BUS_ID_SIZE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) devmap = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * Check if busid has been added to the list of dasd ranges.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) dasd_busid_known(const char *bus_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * Forget all about the device numbers added so far.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * This may only be called at module unload or system shutdown.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) dasd_forget_ranges(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct dasd_devmap *devmap, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) for (i = 0; i < 256; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) BUG_ON(devmap->device != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) list_del(&devmap->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) kfree(devmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * Find the device struct by its device index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct dasd_device *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) dasd_device_from_devindex(int devindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct dasd_devmap *devmap, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) devmap = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) for (i = 0; (i < 256) && !devmap; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) list_for_each_entry(tmp, &dasd_hashlists[i], list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (tmp->devindex == devindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* Found the devmap for the device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) devmap = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (devmap && devmap->device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) device = devmap->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) dasd_get_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) device = ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * Return devmap for cdev. If no devmap exists yet, create one and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * connect it to the cdev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static struct dasd_devmap *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) dasd_devmap_from_cdev(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) devmap = dasd_find_busid(dev_name(&cdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) devmap = dasd_add_busid(dev_name(&cdev->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) DASD_FEATURE_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * Create a dasd device structure for cdev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct dasd_device *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) dasd_create_device(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) devmap = dasd_devmap_from_cdev(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return (void *) devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) device = dasd_alloc_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) atomic_set(&device->ref_count, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (!devmap->device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) devmap->device = device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) device->devindex = devmap->devindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) device->features = devmap->features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) get_device(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) device->cdev = cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /* Someone else was faster. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) dasd_free_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return ERR_PTR(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) dev_set_drvdata(&cdev->dev, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * Wait queue for dasd_delete_device waits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * Remove a dasd device structure. The passed referenced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * is destroyed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) dasd_delete_device(struct dasd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct ccw_device *cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /* First remove device pointer from devmap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) devmap = dasd_find_busid(dev_name(&device->cdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) BUG_ON(IS_ERR(devmap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (devmap->device != device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) devmap->device = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* Disconnect dasd_device structure from ccw_device structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) dev_set_drvdata(&device->cdev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * Drop ref_count by 3, one for the devmap reference, one for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * the cdev reference and one for the passed reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) atomic_sub(3, &device->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /* Wait for reference counter to drop to zero. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) dasd_generic_free_discipline(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /* Disconnect dasd_device structure from ccw_device structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) cdev = device->cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) device->cdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /* Put ccw_device structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) put_device(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /* Now the device structure can be freed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) dasd_free_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * Reference counter dropped to zero. Wake up waiter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * in dasd_delete_device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) dasd_put_device_wake(struct dasd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) wake_up(&dasd_delete_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) EXPORT_SYMBOL_GPL(dasd_put_device_wake);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * Return dasd_device structure associated with cdev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * This function needs to be called with the ccw device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * lock held. It can be used from interrupt context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) struct dasd_device *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) dasd_device_from_cdev_locked(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) struct dasd_device *device = dev_get_drvdata(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (!device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) dasd_get_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * Return dasd_device structure associated with cdev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct dasd_device *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) dasd_device_from_cdev(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) device = dasd_device_from_cdev_locked(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) void dasd_add_link_to_gendisk(struct gendisk *gdp, struct dasd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) devmap = dasd_find_busid(dev_name(&device->cdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) gdp->private_data = devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct dasd_device *dasd_device_from_gendisk(struct gendisk *gdp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (!gdp->private_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) device = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) devmap = gdp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (devmap && devmap->device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) device = devmap->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) dasd_get_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) * SECTION: files in sysfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * failfast controls the behaviour, if no path is available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static ssize_t dasd_ff_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) int ff_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) devmap = dasd_find_busid(dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (!IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) ff_flag = (devmap->features & DASD_FEATURE_FAILFAST) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) ff_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_FAILFAST) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return snprintf(buf, PAGE_SIZE, ff_flag ? "1\n" : "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) static ssize_t dasd_ff_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (kstrtouint(buf, 0, &val) || val > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) rc = dasd_set_feature(to_ccwdev(dev), DASD_FEATURE_FAILFAST, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return rc ? : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) static DEVICE_ATTR(failfast, 0644, dasd_ff_show, dasd_ff_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * readonly controls the readonly status of a dasd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) int ro_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) devmap = dasd_find_busid(dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) ro_flag = !!(devmap->features & DASD_FEATURE_READONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) device = devmap->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) ro_flag |= test_bit(DASD_FLAG_DEVICE_RO, &device->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) dasd_ro_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) struct ccw_device *cdev = to_ccwdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (kstrtouint(buf, 0, &val) || val > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) rc = dasd_set_feature(cdev, DASD_FEATURE_READONLY, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) device = dasd_device_from_cdev(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (!device->block || !device->block->gdp ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) test_bit(DASD_FLAG_OFFLINE, &device->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) /* Increase open_count to avoid losing the block device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) atomic_inc(&device->block->open_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) set_disk_ro(device->block->gdp, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) atomic_dec(&device->block->open_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * erplog controls the logging of ERP related data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * (e.g. failing channel programs).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) dasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) int erplog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) devmap = dasd_find_busid(dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (!IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) erplog = (DASD_FEATURE_DEFAULT & DASD_FEATURE_ERPLOG) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return snprintf(buf, PAGE_SIZE, erplog ? "1\n" : "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) dasd_erplog_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (kstrtouint(buf, 0, &val) || val > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) rc = dasd_set_feature(to_ccwdev(dev), DASD_FEATURE_ERPLOG, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return rc ? : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static DEVICE_ATTR(erplog, 0644, dasd_erplog_show, dasd_erplog_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * use_diag controls whether the driver should use diag rather than ssch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * to talk to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) int use_diag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) devmap = dasd_find_busid(dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (!IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return sprintf(buf, use_diag ? "1\n" : "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) dasd_use_diag_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) ssize_t rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return PTR_ERR(devmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (kstrtouint(buf, 0, &val) || val > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) /* Changing diag discipline flag is only allowed in offline state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) rc = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (!devmap->device && !(devmap->features & DASD_FEATURE_USERAW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) devmap->features |= DASD_FEATURE_USEDIAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) devmap->features &= ~DASD_FEATURE_USEDIAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * use_raw controls whether the driver should give access to raw eckd data or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * operate in standard mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) dasd_use_raw_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) int use_raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) devmap = dasd_find_busid(dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (!IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) use_raw = (devmap->features & DASD_FEATURE_USERAW) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) use_raw = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USERAW) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return sprintf(buf, use_raw ? "1\n" : "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) dasd_use_raw_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ssize_t rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return PTR_ERR(devmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if ((kstrtoul(buf, 10, &val) != 0) || val > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) /* Changing diag discipline flag is only allowed in offline state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) rc = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (!devmap->device && !(devmap->features & DASD_FEATURE_USEDIAG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) devmap->features |= DASD_FEATURE_USERAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) devmap->features &= ~DASD_FEATURE_USERAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static DEVICE_ATTR(raw_track_access, 0644, dasd_use_raw_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) dasd_use_raw_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) dasd_safe_offline_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) struct ccw_device *cdev = to_ccwdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) device = dasd_device_from_cdev_locked(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (IS_ERR(device)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) rc = PTR_ERR(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (test_bit(DASD_FLAG_OFFLINE, &device->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) /* Already doing offline processing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) set_bit(DASD_FLAG_SAFE_OFFLINE, &device->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) rc = ccw_device_set_offline(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return rc ? rc : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static DEVICE_ATTR(safe_offline, 0200, NULL, dasd_safe_offline_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) dasd_access_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct ccw_device *cdev = to_ccwdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) device = dasd_device_from_cdev(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return PTR_ERR(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (!device->discipline)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) count = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) else if (!device->discipline->host_access_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) count = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) count = device->discipline->host_access_count(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (count < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) return sprintf(buf, "%d\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) static DEVICE_ATTR(host_access_count, 0444, dasd_access_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) dasd_discipline_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) ssize_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) else if (!device->discipline) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) len = snprintf(buf, PAGE_SIZE, "%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) device->discipline->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) len = snprintf(buf, PAGE_SIZE, "none\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) dasd_device_status_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) ssize_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (!IS_ERR(device)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) switch (device->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) case DASD_STATE_NEW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) len = snprintf(buf, PAGE_SIZE, "new\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) case DASD_STATE_KNOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) len = snprintf(buf, PAGE_SIZE, "detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) case DASD_STATE_BASIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) len = snprintf(buf, PAGE_SIZE, "basic\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) case DASD_STATE_UNFMT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) len = snprintf(buf, PAGE_SIZE, "unformatted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) case DASD_STATE_READY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) len = snprintf(buf, PAGE_SIZE, "ready\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) case DASD_STATE_ONLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) len = snprintf(buf, PAGE_SIZE, "online\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) len = snprintf(buf, PAGE_SIZE, "no stat\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) len = snprintf(buf, PAGE_SIZE, "unknown\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static ssize_t dasd_alias_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct dasd_uid uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return sprintf(buf, "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (device->discipline && device->discipline->get_uid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) !device->discipline->get_uid(device, &uid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (uid.type == UA_BASE_PAV_ALIAS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) uid.type == UA_HYPER_PAV_ALIAS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return sprintf(buf, "1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) return sprintf(buf, "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) static ssize_t dasd_vendor_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) struct dasd_uid uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) char *vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) vendor = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if (device->discipline && device->discipline->get_uid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) !device->discipline->get_uid(device, &uid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) vendor = uid.vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) #define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial */ 14 + 1 +\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) /* SSID */ 4 + 1 + /* unit addr */ 2 + 1 +\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) /* vduit */ 32 + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct dasd_uid uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) char uid_string[UID_STRLEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) char ua_string[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) uid_string[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (device->discipline && device->discipline->get_uid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) !device->discipline->get_uid(device, &uid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) switch (uid.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) case UA_BASE_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) snprintf(ua_string, sizeof(ua_string), "%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) uid.real_unit_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) case UA_BASE_PAV_ALIAS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) snprintf(ua_string, sizeof(ua_string), "%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) uid.base_unit_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) case UA_HYPER_PAV_ALIAS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) snprintf(ua_string, sizeof(ua_string), "xx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) /* should not happen, treat like base device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) snprintf(ua_string, sizeof(ua_string), "%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) uid.real_unit_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (strlen(uid.vduit) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) snprintf(uid_string, sizeof(uid_string),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) "%s.%s.%04x.%s.%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) uid.vendor, uid.serial, uid.ssid, ua_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) uid.vduit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) snprintf(uid_string, sizeof(uid_string),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) "%s.%s.%04x.%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) uid.vendor, uid.serial, uid.ssid, ua_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) * extended error-reporting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) int eer_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) devmap = dasd_find_busid(dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (!IS_ERR(devmap) && devmap->device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) eer_flag = dasd_eer_enabled(devmap->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) eer_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) dasd_eer_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return PTR_ERR(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (kstrtouint(buf, 0, &val) || val > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) rc = dasd_eer_enable(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) dasd_eer_disable(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) return rc ? : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * expiration time for default requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) dasd_expires_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) len = snprintf(buf, PAGE_SIZE, "%lu\n", device->default_expires);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) dasd_expires_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) if ((kstrtoul(buf, 10, &val) != 0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) (val > DASD_EXPIRES_MAX) || val == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) device->default_expires = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) static DEVICE_ATTR(expires, 0644, dasd_expires_show, dasd_expires_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) dasd_retries_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) len = snprintf(buf, PAGE_SIZE, "%lu\n", device->default_retries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) dasd_retries_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) if ((kstrtoul(buf, 10, &val) != 0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) (val > DASD_RETRIES_MAX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) device->default_retries = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) static DEVICE_ATTR(retries, 0644, dasd_retries_show, dasd_retries_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) dasd_timeout_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) len = snprintf(buf, PAGE_SIZE, "%lu\n", device->blk_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) dasd_timeout_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) struct request_queue *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) if (IS_ERR(device) || !device->block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if ((kstrtoul(buf, 10, &val) != 0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) val > UINT_MAX / HZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) q = device->block->request_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (!q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) device->blk_timeout = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) blk_queue_rq_timeout(q, device->blk_timeout * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) static DEVICE_ATTR(timeout, 0644,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) dasd_timeout_show, dasd_timeout_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) dasd_path_reset_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) if ((kstrtouint(buf, 16, &val) != 0) || val > 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (device->discipline && device->discipline->reset_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) device->discipline->reset_path(device, (__u8) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) static DEVICE_ATTR(path_reset, 0200, NULL, dasd_path_reset_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) static ssize_t dasd_hpf_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) int hpf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if (!device->discipline || !device->discipline->hpf_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) return snprintf(buf, PAGE_SIZE, "%d\n", dasd_nofcx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) hpf = device->discipline->hpf_enabled(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) return snprintf(buf, PAGE_SIZE, "%d\n", hpf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) static DEVICE_ATTR(hpf, 0444, dasd_hpf_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) static ssize_t dasd_reservation_policy_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) devmap = dasd_find_busid(dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) if (IS_ERR(devmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) rc = snprintf(buf, PAGE_SIZE, "ignore\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) if (devmap->features & DASD_FEATURE_FAILONSLCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) rc = snprintf(buf, PAGE_SIZE, "fail\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) rc = snprintf(buf, PAGE_SIZE, "ignore\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) static ssize_t dasd_reservation_policy_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) struct ccw_device *cdev = to_ccwdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (sysfs_streq("ignore", buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) rc = dasd_set_feature(cdev, DASD_FEATURE_FAILONSLCK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) else if (sysfs_streq("fail", buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) rc = dasd_set_feature(cdev, DASD_FEATURE_FAILONSLCK, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) return rc ? : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) static DEVICE_ATTR(reservation_policy, 0644,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) dasd_reservation_policy_show, dasd_reservation_policy_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) static ssize_t dasd_reservation_state_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) return snprintf(buf, PAGE_SIZE, "none\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) if (test_bit(DASD_FLAG_IS_RESERVED, &device->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) rc = snprintf(buf, PAGE_SIZE, "reserved\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) else if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) rc = snprintf(buf, PAGE_SIZE, "lost\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) rc = snprintf(buf, PAGE_SIZE, "none\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) static ssize_t dasd_reservation_state_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) if (sysfs_streq("reset", buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) clear_bit(DASD_FLAG_LOCK_STOLEN, &device->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) static DEVICE_ATTR(last_known_reservation_state, 0644,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) dasd_reservation_state_show, dasd_reservation_state_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) static ssize_t dasd_pm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) u8 opm, nppm, cablepm, cuirpm, hpfpm, ifccpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) return sprintf(buf, "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) opm = dasd_path_get_opm(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) nppm = dasd_path_get_nppm(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) cablepm = dasd_path_get_cablepm(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) cuirpm = dasd_path_get_cuirpm(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) hpfpm = dasd_path_get_hpfpm(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) ifccpm = dasd_path_get_ifccpm(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) return sprintf(buf, "%02x %02x %02x %02x %02x %02x\n", opm, nppm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) cablepm, cuirpm, hpfpm, ifccpm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) static DEVICE_ATTR(path_masks, 0444, dasd_pm_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) * threshold value for IFCC/CCC errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) dasd_path_threshold_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) len = snprintf(buf, PAGE_SIZE, "%lu\n", device->path_thrhld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) dasd_path_threshold_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) if (kstrtoul(buf, 10, &val) != 0 || val > DASD_THRHLD_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) spin_lock_irqsave(get_ccwdev_lock(to_ccwdev(dev)), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) device->path_thrhld = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) spin_unlock_irqrestore(get_ccwdev_lock(to_ccwdev(dev)), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) static DEVICE_ATTR(path_threshold, 0644, dasd_path_threshold_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) dasd_path_threshold_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) * configure if path is disabled after IFCC/CCC error threshold is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) * exceeded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) dasd_path_autodisable_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) int flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) devmap = dasd_find_busid(dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) if (!IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) flag = (devmap->features & DASD_FEATURE_PATH_AUTODISABLE) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) flag = (DASD_FEATURE_DEFAULT &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) DASD_FEATURE_PATH_AUTODISABLE) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) return snprintf(buf, PAGE_SIZE, flag ? "1\n" : "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) dasd_path_autodisable_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) if (kstrtouint(buf, 0, &val) || val > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) rc = dasd_set_feature(to_ccwdev(dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) DASD_FEATURE_PATH_AUTODISABLE, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) return rc ? : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) static DEVICE_ATTR(path_autodisable, 0644,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) dasd_path_autodisable_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) dasd_path_autodisable_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) * interval for IFCC/CCC checks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) * meaning time with no IFCC/CCC error before the error counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) * gets reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) dasd_path_interval_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) len = snprintf(buf, PAGE_SIZE, "%lu\n", device->path_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) dasd_path_interval_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) struct dasd_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) device = dasd_device_from_cdev(to_ccwdev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) if (IS_ERR(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) if ((kstrtoul(buf, 10, &val) != 0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) (val > DASD_INTERVAL_MAX) || val == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) spin_lock_irqsave(get_ccwdev_lock(to_ccwdev(dev)), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) device->path_interval = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) spin_unlock_irqrestore(get_ccwdev_lock(to_ccwdev(dev)), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) dasd_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) static DEVICE_ATTR(path_interval, 0644, dasd_path_interval_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) dasd_path_interval_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) #define DASD_DEFINE_ATTR(_name, _func) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) static ssize_t dasd_##_name##_show(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) struct ccw_device *cdev = to_ccwdev(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) struct dasd_device *device = dasd_device_from_cdev(cdev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) int val = 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) if (IS_ERR(device)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) return -ENODEV; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) if (device->discipline && _func) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) val = _func(device); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) dasd_put_device(device); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) return snprintf(buf, PAGE_SIZE, "%d\n", val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) static DEVICE_ATTR(_name, 0444, dasd_##_name##_show, NULL); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) DASD_DEFINE_ATTR(ese, device->discipline->is_ese);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) DASD_DEFINE_ATTR(extent_size, device->discipline->ext_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) DASD_DEFINE_ATTR(pool_id, device->discipline->ext_pool_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) DASD_DEFINE_ATTR(space_configured, device->discipline->space_configured);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) DASD_DEFINE_ATTR(space_allocated, device->discipline->space_allocated);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) DASD_DEFINE_ATTR(logical_capacity, device->discipline->logical_capacity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) DASD_DEFINE_ATTR(warn_threshold, device->discipline->ext_pool_warn_thrshld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) DASD_DEFINE_ATTR(cap_at_warnlevel, device->discipline->ext_pool_cap_at_warnlevel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) DASD_DEFINE_ATTR(pool_oos, device->discipline->ext_pool_oos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) static struct attribute * dasd_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) &dev_attr_readonly.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) &dev_attr_discipline.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) &dev_attr_status.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) &dev_attr_alias.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) &dev_attr_vendor.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) &dev_attr_uid.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) &dev_attr_use_diag.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) &dev_attr_raw_track_access.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) &dev_attr_eer_enabled.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) &dev_attr_erplog.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) &dev_attr_failfast.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) &dev_attr_expires.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) &dev_attr_retries.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) &dev_attr_timeout.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) &dev_attr_reservation_policy.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) &dev_attr_last_known_reservation_state.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) &dev_attr_safe_offline.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) &dev_attr_host_access_count.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) &dev_attr_path_masks.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) &dev_attr_path_threshold.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) &dev_attr_path_autodisable.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) &dev_attr_path_interval.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) &dev_attr_path_reset.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) &dev_attr_hpf.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) &dev_attr_ese.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) static const struct attribute_group dasd_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) .attrs = dasd_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) static struct attribute *capacity_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) &dev_attr_space_configured.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) &dev_attr_space_allocated.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) &dev_attr_logical_capacity.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) static const struct attribute_group capacity_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) .name = "capacity",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) .attrs = capacity_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) static struct attribute *ext_pool_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) &dev_attr_pool_id.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) &dev_attr_extent_size.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) &dev_attr_warn_threshold.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) &dev_attr_cap_at_warnlevel.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) &dev_attr_pool_oos.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) static const struct attribute_group ext_pool_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) .name = "extent_pool",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) .attrs = ext_pool_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) static const struct attribute_group *dasd_attr_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) &dasd_attr_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) &capacity_attr_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) &ext_pool_attr_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) * Return value of the specified feature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) dasd_get_feature(struct ccw_device *cdev, int feature)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) devmap = dasd_find_busid(dev_name(&cdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) if (IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) return PTR_ERR(devmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) return ((devmap->features & feature) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) * Set / reset given feature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) * Flag indicates whether to set (!=0) or the reset (=0) the feature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) struct dasd_devmap *devmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) devmap = dasd_devmap_from_cdev(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) if (IS_ERR(devmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) return PTR_ERR(devmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) spin_lock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) if (flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) devmap->features |= feature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) devmap->features &= ~feature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) if (devmap->device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) devmap->device->features = devmap->features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) spin_unlock(&dasd_devmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) EXPORT_SYMBOL(dasd_set_feature);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) int dasd_add_sysfs_files(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) return sysfs_create_groups(&cdev->dev.kobj, dasd_attr_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) dasd_remove_sysfs_files(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) sysfs_remove_groups(&cdev->dev.kobj, dasd_attr_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) dasd_devmap_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) /* Initialize devmap structures. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) dasd_max_devindex = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) for (i = 0; i < 256; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) INIT_LIST_HEAD(&dasd_hashlists[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) dasd_devmap_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) dasd_forget_ranges();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) }