]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | commit ab1d848fd6a9151b02c6cbf4bddce6e24707b094 |
2 | From: Nigel Hislop <hislop_nigel@emc.com> | |
3 | Date: Fri Oct 10 21:33:25 2008 +0200 | |
4 | Subject: Add ioctl support for EMC Symmetrix Subsystem Control I/O | |
5 | References: bnc#439221 | |
6 | ||
7 | EMC Symmetrix Subsystem Control I/O through CKD dasd requires a | |
8 | specific parameter list sent to the array via a Perform Subsystem | |
9 | Function CCW. The Symmetrix response is retrieved from the array | |
10 | via a Read Subsystem Data CCW. | |
11 | ||
12 | Signed-off-by: Nigel Hislop <hislop_nigel@emc.com> | |
13 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
14 | Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> | |
15 | ||
16 | --- | |
17 | arch/s390/include/asm/dasd.h | 13 +++++ | |
18 | drivers/s390/block/dasd_eckd.c | 101 +++++++++++++++++++++++++++++++++++++++++ | |
19 | 2 files changed, 114 insertions(+) | |
20 | ||
21 | --- a/arch/s390/include/asm/dasd.h | |
22 | +++ b/arch/s390/include/asm/dasd.h | |
23 | @@ -3,6 +3,8 @@ | |
24 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | |
25 | * Bugreports.to..: <Linux390@de.ibm.com> | |
26 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 | |
27 | + * EMC Symmetrix ioctl Copyright EMC Corporation, 2008 | |
28 | + * Author.........: Nigel Hislop <hislop_nigel@emc.com> | |
29 | * | |
30 | * This file is the interface of the DASD device driver, which is exported to user space | |
31 | * any future changes wrt the API will result in a change of the APIVERSION reported | |
32 | @@ -202,6 +204,16 @@ typedef struct attrib_data_t { | |
33 | #define DASD_SEQ_PRESTAGE 0x4 | |
34 | #define DASD_REC_ACCESS 0x5 | |
35 | ||
36 | +/* | |
37 | + * Perform EMC Symmetrix I/O | |
38 | + */ | |
39 | +typedef struct dasd_symmio_parms { | |
40 | + unsigned char reserved[8]; /* compat with older releases */ | |
41 | + unsigned long long psf_data; /* char * cast to u64 */ | |
42 | + unsigned long long rssd_result; /* char * cast to u64 */ | |
43 | + int psf_data_len; | |
44 | + int rssd_result_len; | |
45 | +} __attribute__ ((packed)) dasd_symmio_parms_t; | |
46 | ||
47 | /******************************************************************************** | |
48 | * SECTION: Definition of IOCTLs | |
49 | @@ -247,6 +259,7 @@ typedef struct attrib_data_t { | |
50 | /* Set Attributes (cache operations) */ | |
51 | #define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) | |
52 | ||
53 | +#define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t) | |
54 | ||
55 | #endif /* DASD_H */ | |
56 | ||
57 | --- a/drivers/s390/block/dasd_eckd.c | |
58 | +++ b/drivers/s390/block/dasd_eckd.c | |
59 | @@ -6,6 +6,8 @@ | |
60 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | |
61 | * Bugreports.to..: <Linux390@de.ibm.com> | |
62 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 | |
63 | + * EMC Symmetrix ioctl Copyright EMC Corporation, 2008 | |
64 | + * Author.........: Nigel Hislop <hislop_nigel@emc.com> | |
65 | * | |
66 | */ | |
67 | ||
68 | @@ -2083,6 +2085,103 @@ dasd_eckd_set_attrib(struct dasd_device | |
69 | return 0; | |
70 | } | |
71 | ||
72 | +/* | |
73 | + * Issue syscall I/O to EMC Symmetrix array. | |
74 | + * CCWs are PSF and RSSD | |
75 | + */ | |
76 | +static int dasd_symm_io(struct dasd_device *device, void __user *argp) | |
77 | +{ | |
78 | + struct dasd_symmio_parms usrparm; | |
79 | + char *psf_data, *rssd_result; | |
80 | + struct dasd_ccw_req *cqr; | |
81 | + struct ccw1 *ccw; | |
82 | + int rc; | |
83 | + | |
84 | + /* Copy parms from caller */ | |
85 | + rc = -EFAULT; | |
86 | + if (copy_from_user(&usrparm, argp, sizeof(usrparm))) | |
87 | + goto out; | |
88 | +#ifndef CONFIG_64BIT | |
89 | + /* Make sure pointers are sane even on 31 bit. */ | |
90 | + if ((usrparm.psf_data >> 32) != 0 || (usrparm.rssd_result >> 32) != 0) { | |
91 | + rc = -EINVAL; | |
92 | + goto out; | |
93 | + } | |
94 | +#endif | |
95 | + /* alloc I/O data area */ | |
96 | + psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA); | |
97 | + rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA); | |
98 | + if (!psf_data || !rssd_result) { | |
99 | + rc = -ENOMEM; | |
100 | + goto out_free; | |
101 | + } | |
102 | + | |
103 | + /* get syscall header from user space */ | |
104 | + rc = -EFAULT; | |
105 | + if (copy_from_user(psf_data, | |
106 | + (void __user *)(unsigned long) usrparm.psf_data, | |
107 | + usrparm.psf_data_len)) | |
108 | + goto out_free; | |
109 | + | |
110 | + /* sanity check on syscall header */ | |
111 | + if (psf_data[0] != 0x17 && psf_data[1] != 0xce) { | |
112 | + rc = -EINVAL; | |
113 | + goto out_free; | |
114 | + } | |
115 | + | |
116 | + /* setup CCWs for PSF + RSSD */ | |
117 | + cqr = dasd_smalloc_request("ECKD", 2 , 0, device); | |
118 | + if (IS_ERR(cqr)) { | |
119 | + DEV_MESSAGE(KERN_WARNING, device, "%s", | |
120 | + "Could not allocate initialization request"); | |
121 | + rc = PTR_ERR(cqr); | |
122 | + goto out_free; | |
123 | + } | |
124 | + | |
125 | + cqr->startdev = device; | |
126 | + cqr->memdev = device; | |
127 | + cqr->retries = 3; | |
128 | + cqr->expires = 10 * HZ; | |
129 | + cqr->buildclk = get_clock(); | |
130 | + cqr->status = DASD_CQR_FILLED; | |
131 | + | |
132 | + /* Build the ccws */ | |
133 | + ccw = cqr->cpaddr; | |
134 | + | |
135 | + /* PSF ccw */ | |
136 | + ccw->cmd_code = DASD_ECKD_CCW_PSF; | |
137 | + ccw->count = usrparm.psf_data_len; | |
138 | + ccw->flags |= CCW_FLAG_CC; | |
139 | + ccw->cda = (__u32)(addr_t) psf_data; | |
140 | + | |
141 | + ccw++; | |
142 | + | |
143 | + /* RSSD ccw */ | |
144 | + ccw->cmd_code = DASD_ECKD_CCW_RSSD; | |
145 | + ccw->count = usrparm.rssd_result_len; | |
146 | + ccw->flags = CCW_FLAG_SLI ; | |
147 | + ccw->cda = (__u32)(addr_t) rssd_result; | |
148 | + | |
149 | + rc = dasd_sleep_on(cqr); | |
150 | + if (rc) | |
151 | + goto out_sfree; | |
152 | + | |
153 | + rc = -EFAULT; | |
154 | + if (copy_to_user((void __user *)(unsigned long) usrparm.rssd_result, | |
155 | + rssd_result, usrparm.rssd_result_len)) | |
156 | + goto out_sfree; | |
157 | + rc = 0; | |
158 | + | |
159 | +out_sfree: | |
160 | + dasd_sfree_request(cqr, cqr->memdev); | |
161 | +out_free: | |
162 | + kfree(rssd_result); | |
163 | + kfree(psf_data); | |
164 | +out: | |
165 | + DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc); | |
166 | + return rc; | |
167 | +} | |
168 | + | |
169 | static int | |
170 | dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) | |
171 | { | |
172 | @@ -2101,6 +2200,8 @@ dasd_eckd_ioctl(struct dasd_block *block | |
173 | return dasd_eckd_reserve(device); | |
174 | case BIODASDSLCK: | |
175 | return dasd_eckd_steal_lock(device); | |
176 | + case BIODASDSYMMIO: | |
177 | + return dasd_symm_io(device, argp); | |
178 | default: | |
179 | return -ENOIOCTLCMD; | |
180 | } |