diff options
| author | Nigel Hislop <hislop_nigel@emc.com> | 2008-10-10 15:33:25 -0400 |
|---|---|---|
| committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-10-10 15:34:00 -0400 |
| commit | ab1d848fd6a9151b02c6cbf4bddce6e24707b094 (patch) | |
| tree | 6476c68b552e2df56a0ebd293d0c9777c735480b | |
| parent | 3ce66093f5ec5a6ae0ca90c79d81eee15e842293 (diff) | |
[S390] Add ioctl support for EMC Symmetrix Subsystem Control I/O
EMC Symmetrix Subsystem Control I/O through CKD dasd requires a
specific parameter list sent to the array via a Perform Subsystem
Function CCW. The Symmetrix response is retrieved from the array
via a Read Subsystem Data CCW.
Signed-off-by: Nigel Hislop <hislop_nigel@emc.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
| -rw-r--r-- | arch/s390/include/asm/dasd.h | 13 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_eckd.c | 101 |
2 files changed, 114 insertions, 0 deletions
diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h index 3f002e13d024..55b2b80cdf6e 100644 --- a/arch/s390/include/asm/dasd.h +++ b/arch/s390/include/asm/dasd.h | |||
| @@ -3,6 +3,8 @@ | |||
| 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
| 4 | * Bugreports.to..: <Linux390@de.ibm.com> | 4 | * Bugreports.to..: <Linux390@de.ibm.com> |
| 5 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 | 5 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 |
| 6 | * EMC Symmetrix ioctl Copyright EMC Corporation, 2008 | ||
| 7 | * Author.........: Nigel Hislop <hislop_nigel@emc.com> | ||
| 6 | * | 8 | * |
| 7 | * This file is the interface of the DASD device driver, which is exported to user space | 9 | * This file is the interface of the DASD device driver, which is exported to user space |
| 8 | * any future changes wrt the API will result in a change of the APIVERSION reported | 10 | * any future changes wrt the API will result in a change of the APIVERSION reported |
| @@ -202,6 +204,16 @@ typedef struct attrib_data_t { | |||
| 202 | #define DASD_SEQ_PRESTAGE 0x4 | 204 | #define DASD_SEQ_PRESTAGE 0x4 |
| 203 | #define DASD_REC_ACCESS 0x5 | 205 | #define DASD_REC_ACCESS 0x5 |
| 204 | 206 | ||
| 207 | /* | ||
| 208 | * Perform EMC Symmetrix I/O | ||
| 209 | */ | ||
| 210 | typedef struct dasd_symmio_parms { | ||
| 211 | unsigned char reserved[8]; /* compat with older releases */ | ||
| 212 | unsigned long long psf_data; /* char * cast to u64 */ | ||
| 213 | unsigned long long rssd_result; /* char * cast to u64 */ | ||
| 214 | int psf_data_len; | ||
| 215 | int rssd_result_len; | ||
| 216 | } __attribute__ ((packed)) dasd_symmio_parms_t; | ||
| 205 | 217 | ||
| 206 | /******************************************************************************** | 218 | /******************************************************************************** |
| 207 | * SECTION: Definition of IOCTLs | 219 | * SECTION: Definition of IOCTLs |
| @@ -247,6 +259,7 @@ typedef struct attrib_data_t { | |||
| 247 | /* Set Attributes (cache operations) */ | 259 | /* Set Attributes (cache operations) */ |
| 248 | #define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) | 260 | #define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) |
| 249 | 261 | ||
| 262 | #define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t) | ||
| 250 | 263 | ||
| 251 | #endif /* DASD_H */ | 264 | #endif /* DASD_H */ |
| 252 | 265 | ||
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 8095629bc493..49f9d221e23d 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 6 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
| 7 | * Bugreports.to..: <Linux390@de.ibm.com> | 7 | * Bugreports.to..: <Linux390@de.ibm.com> |
| 8 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 | 8 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 |
| 9 | * EMC Symmetrix ioctl Copyright EMC Corporation, 2008 | ||
| 10 | * Author.........: Nigel Hislop <hislop_nigel@emc.com> | ||
| 9 | * | 11 | * |
| 10 | */ | 12 | */ |
| 11 | 13 | ||
| @@ -2083,6 +2085,103 @@ dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp) | |||
| 2083 | return 0; | 2085 | return 0; |
| 2084 | } | 2086 | } |
| 2085 | 2087 | ||
| 2088 | /* | ||
| 2089 | * Issue syscall I/O to EMC Symmetrix array. | ||
| 2090 | * CCWs are PSF and RSSD | ||
| 2091 | */ | ||
| 2092 | static int dasd_symm_io(struct dasd_device *device, void __user *argp) | ||
| 2093 | { | ||
| 2094 | struct dasd_symmio_parms usrparm; | ||
| 2095 | char *psf_data, *rssd_result; | ||
| 2096 | struct dasd_ccw_req *cqr; | ||
| 2097 | struct ccw1 *ccw; | ||
| 2098 | int rc; | ||
| 2099 | |||
| 2100 | /* Copy parms from caller */ | ||
| 2101 | rc = -EFAULT; | ||
| 2102 | if (copy_from_user(&usrparm, argp, sizeof(usrparm))) | ||
| 2103 | goto out; | ||
| 2104 | #ifndef CONFIG_64BIT | ||
| 2105 | /* Make sure pointers are sane even on 31 bit. */ | ||
| 2106 | if ((usrparm.psf_data >> 32) != 0 || (usrparm.rssd_result >> 32) != 0) { | ||
| 2107 | rc = -EINVAL; | ||
| 2108 | goto out; | ||
| 2109 | } | ||
| 2110 | #endif | ||
| 2111 | /* alloc I/O data area */ | ||
| 2112 | psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA); | ||
| 2113 | rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA); | ||
| 2114 | if (!psf_data || !rssd_result) { | ||
| 2115 | rc = -ENOMEM; | ||
| 2116 | goto out_free; | ||
| 2117 | } | ||
| 2118 | |||
| 2119 | /* get syscall header from user space */ | ||
| 2120 | rc = -EFAULT; | ||
| 2121 | if (copy_from_user(psf_data, | ||
| 2122 | (void __user *)(unsigned long) usrparm.psf_data, | ||
| 2123 | usrparm.psf_data_len)) | ||
| 2124 | goto out_free; | ||
| 2125 | |||
| 2126 | /* sanity check on syscall header */ | ||
| 2127 | if (psf_data[0] != 0x17 && psf_data[1] != 0xce) { | ||
| 2128 | rc = -EINVAL; | ||
| 2129 | goto out_free; | ||
| 2130 | } | ||
| 2131 | |||
| 2132 | /* setup CCWs for PSF + RSSD */ | ||
| 2133 | cqr = dasd_smalloc_request("ECKD", 2 , 0, device); | ||
| 2134 | if (IS_ERR(cqr)) { | ||
| 2135 | DEV_MESSAGE(KERN_WARNING, device, "%s", | ||
| 2136 | "Could not allocate initialization request"); | ||
| 2137 | rc = PTR_ERR(cqr); | ||
| 2138 | goto out_free; | ||
| 2139 | } | ||
| 2140 | |||
| 2141 | cqr->startdev = device; | ||
| 2142 | cqr->memdev = device; | ||
| 2143 | cqr->retries = 3; | ||
| 2144 | cqr->expires = 10 * HZ; | ||
| 2145 | cqr->buildclk = get_clock(); | ||
| 2146 | cqr->status = DASD_CQR_FILLED; | ||
| 2147 | |||
| 2148 | /* Build the ccws */ | ||
| 2149 | ccw = cqr->cpaddr; | ||
| 2150 | |||
| 2151 | /* PSF ccw */ | ||
| 2152 | ccw->cmd_code = DASD_ECKD_CCW_PSF; | ||
| 2153 | ccw->count = usrparm.psf_data_len; | ||
| 2154 | ccw->flags |= CCW_FLAG_CC; | ||
| 2155 | ccw->cda = (__u32)(addr_t) psf_data; | ||
| 2156 | |||
| 2157 | ccw++; | ||
| 2158 | |||
| 2159 | /* RSSD ccw */ | ||
| 2160 | ccw->cmd_code = DASD_ECKD_CCW_RSSD; | ||
| 2161 | ccw->count = usrparm.rssd_result_len; | ||
| 2162 | ccw->flags = CCW_FLAG_SLI ; | ||
| 2163 | ccw->cda = (__u32)(addr_t) rssd_result; | ||
| 2164 | |||
| 2165 | rc = dasd_sleep_on(cqr); | ||
| 2166 | if (rc) | ||
| 2167 | goto out_sfree; | ||
| 2168 | |||
| 2169 | rc = -EFAULT; | ||
| 2170 | if (copy_to_user((void __user *)(unsigned long) usrparm.rssd_result, | ||
| 2171 | rssd_result, usrparm.rssd_result_len)) | ||
| 2172 | goto out_sfree; | ||
| 2173 | rc = 0; | ||
| 2174 | |||
| 2175 | out_sfree: | ||
| 2176 | dasd_sfree_request(cqr, cqr->memdev); | ||
| 2177 | out_free: | ||
| 2178 | kfree(rssd_result); | ||
| 2179 | kfree(psf_data); | ||
| 2180 | out: | ||
| 2181 | DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc); | ||
| 2182 | return rc; | ||
| 2183 | } | ||
| 2184 | |||
| 2086 | static int | 2185 | static int |
| 2087 | dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) | 2186 | dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) |
| 2088 | { | 2187 | { |
| @@ -2101,6 +2200,8 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) | |||
| 2101 | return dasd_eckd_reserve(device); | 2200 | return dasd_eckd_reserve(device); |
| 2102 | case BIODASDSLCK: | 2201 | case BIODASDSLCK: |
| 2103 | return dasd_eckd_steal_lock(device); | 2202 | return dasd_eckd_steal_lock(device); |
| 2203 | case BIODASDSYMMIO: | ||
| 2204 | return dasd_symm_io(device, argp); | ||
| 2104 | default: | 2205 | default: |
| 2105 | return -ENOIOCTLCMD; | 2206 | return -ENOIOCTLCMD; |
| 2106 | } | 2207 | } |
