diff options
Diffstat (limited to 'drivers/s390/cio/cmf.c')
-rw-r--r-- | drivers/s390/cio/cmf.c | 63 |
1 files changed, 14 insertions, 49 deletions
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index a90b28c0be57..dc98b2c63862 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c | |||
@@ -25,6 +25,9 @@ | |||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define KMSG_COMPONENT "cio" | ||
29 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
30 | |||
28 | #include <linux/bootmem.h> | 31 | #include <linux/bootmem.h> |
29 | #include <linux/device.h> | 32 | #include <linux/device.h> |
30 | #include <linux/init.h> | 33 | #include <linux/init.h> |
@@ -185,56 +188,19 @@ static inline void cmf_activate(void *area, unsigned int onoff) | |||
185 | static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, | 188 | static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, |
186 | unsigned long address) | 189 | unsigned long address) |
187 | { | 190 | { |
188 | int ret; | ||
189 | int retry; | ||
190 | struct subchannel *sch; | 191 | struct subchannel *sch; |
191 | struct schib *schib; | ||
192 | 192 | ||
193 | sch = to_subchannel(cdev->dev.parent); | 193 | sch = to_subchannel(cdev->dev.parent); |
194 | schib = &sch->schib; | ||
195 | /* msch can silently fail, so do it again if necessary */ | ||
196 | for (retry = 0; retry < 3; retry++) { | ||
197 | /* prepare schib */ | ||
198 | stsch(sch->schid, schib); | ||
199 | schib->pmcw.mme = mme; | ||
200 | schib->pmcw.mbfc = mbfc; | ||
201 | /* address can be either a block address or a block index */ | ||
202 | if (mbfc) | ||
203 | schib->mba = address; | ||
204 | else | ||
205 | schib->pmcw.mbi = address; | ||
206 | |||
207 | /* try to submit it */ | ||
208 | switch(ret = msch_err(sch->schid, schib)) { | ||
209 | case 0: | ||
210 | break; | ||
211 | case 1: | ||
212 | case 2: /* in I/O or status pending */ | ||
213 | ret = -EBUSY; | ||
214 | break; | ||
215 | case 3: /* subchannel is no longer valid */ | ||
216 | ret = -ENODEV; | ||
217 | break; | ||
218 | default: /* msch caught an exception */ | ||
219 | ret = -EINVAL; | ||
220 | break; | ||
221 | } | ||
222 | stsch(sch->schid, schib); /* restore the schib */ | ||
223 | |||
224 | if (ret) | ||
225 | break; | ||
226 | 194 | ||
227 | /* check if it worked */ | 195 | sch->config.mme = mme; |
228 | if (schib->pmcw.mme == mme && | 196 | sch->config.mbfc = mbfc; |
229 | schib->pmcw.mbfc == mbfc && | 197 | /* address can be either a block address or a block index */ |
230 | (mbfc ? (schib->mba == address) | 198 | if (mbfc) |
231 | : (schib->pmcw.mbi == address))) | 199 | sch->config.mba = address; |
232 | return 0; | 200 | else |
201 | sch->config.mbi = address; | ||
233 | 202 | ||
234 | ret = -EINVAL; | 203 | return cio_commit_config(sch); |
235 | } | ||
236 | |||
237 | return ret; | ||
238 | } | 204 | } |
239 | 205 | ||
240 | struct set_schib_struct { | 206 | struct set_schib_struct { |
@@ -338,7 +304,7 @@ static int cmf_copy_block(struct ccw_device *cdev) | |||
338 | 304 | ||
339 | sch = to_subchannel(cdev->dev.parent); | 305 | sch = to_subchannel(cdev->dev.parent); |
340 | 306 | ||
341 | if (stsch(sch->schid, &sch->schib)) | 307 | if (cio_update_schib(sch)) |
342 | return -ENODEV; | 308 | return -ENODEV; |
343 | 309 | ||
344 | if (scsw_fctl(&sch->schib.scsw) & SCSW_FCTL_START_FUNC) { | 310 | if (scsw_fctl(&sch->schib.scsw) & SCSW_FCTL_START_FUNC) { |
@@ -1359,9 +1325,8 @@ static int __init init_cmf(void) | |||
1359 | default: | 1325 | default: |
1360 | return 1; | 1326 | return 1; |
1361 | } | 1327 | } |
1362 | 1328 | pr_info("Channel measurement facility initialized using format " | |
1363 | printk(KERN_INFO "cio: Channel measurement facility using %s " | 1329 | "%s (mode %s)\n", format_string, detect_string); |
1364 | "format (%s)\n", format_string, detect_string); | ||
1365 | return 0; | 1330 | return 0; |
1366 | } | 1331 | } |
1367 | 1332 | ||