diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2008-12-25 07:39:13 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-12-25 07:39:10 -0500 |
commit | 13952ec12dfeea793ff83c2a96139ed57eb0b897 (patch) | |
tree | 3311df62a1794bf95f78b2c57f25f0a79dc84523 /drivers/s390/cio | |
parent | cdb912a40df8b8507ab60b3d52f9980c0ba1f44d (diff) |
[S390] cio: introduce cio_commit_config
To change the configuration of a subchannel we alter the modifiable
bits of the subchannel's schib field and issue a modify subchannel.
There can be the case that not all changes were applied -or worse-
quietly overwritten by the hardware. With the next store subchannel
we obtain the current state of the hardware but lose our target
configuration.
With this patch we introduce a subchannel_config structure which
contains the target subchannel configuration. Additionally the msch
wrapper cio_modify is replaced with cio_commit_config which
copies the desired changes to a temporary schib. msch is then
called with the temporary schib. This schib is only written back
to the subchannel if all changes were applied.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r-- | drivers/s390/cio/cio.c | 134 | ||||
-rw-r--r-- | drivers/s390/cio/cio.h | 16 | ||||
-rw-r--r-- | drivers/s390/cio/cmf.c | 55 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 4 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 36 | ||||
-rw-r--r-- | drivers/s390/cio/device.h | 1 | ||||
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 11 |
7 files changed, 123 insertions, 134 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 9bdb463765c7..8f1cec499532 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -330,30 +330,70 @@ cio_cancel (struct subchannel *sch) | |||
330 | } | 330 | } |
331 | } | 331 | } |
332 | 332 | ||
333 | |||
334 | static void cio_apply_config(struct subchannel *sch, struct schib *schib) | ||
335 | { | ||
336 | schib->pmcw.intparm = sch->config.intparm; | ||
337 | schib->pmcw.mbi = sch->config.mbi; | ||
338 | schib->pmcw.isc = sch->config.isc; | ||
339 | schib->pmcw.ena = sch->config.ena; | ||
340 | schib->pmcw.mme = sch->config.mme; | ||
341 | schib->pmcw.mp = sch->config.mp; | ||
342 | schib->pmcw.csense = sch->config.csense; | ||
343 | schib->pmcw.mbfc = sch->config.mbfc; | ||
344 | if (sch->config.mbfc) | ||
345 | schib->mba = sch->config.mba; | ||
346 | } | ||
347 | |||
348 | static int cio_check_config(struct subchannel *sch, struct schib *schib) | ||
349 | { | ||
350 | return (schib->pmcw.intparm == sch->config.intparm) && | ||
351 | (schib->pmcw.mbi == sch->config.mbi) && | ||
352 | (schib->pmcw.isc == sch->config.isc) && | ||
353 | (schib->pmcw.ena == sch->config.ena) && | ||
354 | (schib->pmcw.mme == sch->config.mme) && | ||
355 | (schib->pmcw.mp == sch->config.mp) && | ||
356 | (schib->pmcw.csense == sch->config.csense) && | ||
357 | (schib->pmcw.mbfc == sch->config.mbfc) && | ||
358 | (!sch->config.mbfc || (schib->mba == sch->config.mba)); | ||
359 | } | ||
360 | |||
333 | /* | 361 | /* |
334 | * Function: cio_modify | 362 | * cio_commit_config - apply configuration to the subchannel |
335 | * Issues a "Modify Subchannel" on the specified subchannel | ||
336 | */ | 363 | */ |
337 | int | 364 | int cio_commit_config(struct subchannel *sch) |
338 | cio_modify (struct subchannel *sch) | ||
339 | { | 365 | { |
340 | int ccode, retry, ret; | 366 | struct schib schib; |
367 | int ccode, retry, ret = 0; | ||
368 | |||
369 | if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib)) | ||
370 | return -ENODEV; | ||
341 | 371 | ||
342 | ret = 0; | ||
343 | for (retry = 0; retry < 5; retry++) { | 372 | for (retry = 0; retry < 5; retry++) { |
344 | ccode = msch_err (sch->schid, &sch->schib); | 373 | /* copy desired changes to local schib */ |
345 | if (ccode < 0) /* -EIO if msch gets a program check. */ | 374 | cio_apply_config(sch, &schib); |
375 | ccode = msch_err(sch->schid, &schib); | ||
376 | if (ccode < 0) /* -EIO if msch gets a program check. */ | ||
346 | return ccode; | 377 | return ccode; |
347 | switch (ccode) { | 378 | switch (ccode) { |
348 | case 0: /* successfull */ | 379 | case 0: /* successfull */ |
349 | return 0; | 380 | if (stsch(sch->schid, &schib) || |
350 | case 1: /* status pending */ | 381 | !css_sch_is_valid(&schib)) |
382 | return -ENODEV; | ||
383 | if (cio_check_config(sch, &schib)) { | ||
384 | /* commit changes from local schib */ | ||
385 | memcpy(&sch->schib, &schib, sizeof(schib)); | ||
386 | return 0; | ||
387 | } | ||
388 | ret = -EAGAIN; | ||
389 | break; | ||
390 | case 1: /* status pending */ | ||
351 | return -EBUSY; | 391 | return -EBUSY; |
352 | case 2: /* busy */ | 392 | case 2: /* busy */ |
353 | udelay (100); /* allow for recovery */ | 393 | udelay(100); /* allow for recovery */ |
354 | ret = -EBUSY; | 394 | ret = -EBUSY; |
355 | break; | 395 | break; |
356 | case 3: /* not operational */ | 396 | case 3: /* not operational */ |
357 | return -ENODEV; | 397 | return -ENODEV; |
358 | } | 398 | } |
359 | } | 399 | } |
@@ -396,32 +436,24 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm) | |||
396 | if (cio_update_schib(sch)) | 436 | if (cio_update_schib(sch)) |
397 | return -ENODEV; | 437 | return -ENODEV; |
398 | 438 | ||
399 | for (retry = 5, ret = 0; retry > 0; retry--) { | 439 | sch->config.ena = 1; |
400 | sch->schib.pmcw.ena = 1; | 440 | sch->config.isc = sch->isc; |
401 | sch->schib.pmcw.isc = sch->isc; | 441 | sch->config.intparm = intparm; |
402 | sch->schib.pmcw.intparm = intparm; | 442 | |
403 | ret = cio_modify(sch); | 443 | for (retry = 0; retry < 3; retry++) { |
404 | if (ret == -ENODEV) | 444 | ret = cio_commit_config(sch); |
405 | break; | 445 | if (ret == -EIO) { |
406 | if (ret == -EIO) | ||
407 | /* | 446 | /* |
408 | * Got a program check in cio_modify. Try without | 447 | * Got a program check in msch. Try without |
409 | * the concurrent sense bit the next time. | 448 | * the concurrent sense bit the next time. |
410 | */ | 449 | */ |
411 | sch->schib.pmcw.csense = 0; | 450 | sch->config.csense = 0; |
412 | if (ret == 0) { | 451 | } else if (ret == -EBUSY) { |
413 | if (cio_update_schib(sch)) { | ||
414 | ret = -ENODEV; | ||
415 | break; | ||
416 | } | ||
417 | if (sch->schib.pmcw.ena) | ||
418 | break; | ||
419 | } | ||
420 | if (ret == -EBUSY) { | ||
421 | struct irb irb; | 452 | struct irb irb; |
422 | if (tsch(sch->schid, &irb) != 0) | 453 | if (tsch(sch->schid, &irb) != 0) |
423 | break; | 454 | break; |
424 | } | 455 | } else |
456 | break; | ||
425 | } | 457 | } |
426 | sprintf (dbf_txt, "ret:%d", ret); | 458 | sprintf (dbf_txt, "ret:%d", ret); |
427 | CIO_TRACE_EVENT (2, dbf_txt); | 459 | CIO_TRACE_EVENT (2, dbf_txt); |
@@ -436,7 +468,6 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel); | |||
436 | int cio_disable_subchannel(struct subchannel *sch) | 468 | int cio_disable_subchannel(struct subchannel *sch) |
437 | { | 469 | { |
438 | char dbf_txt[15]; | 470 | char dbf_txt[15]; |
439 | int retry; | ||
440 | int ret; | 471 | int ret; |
441 | 472 | ||
442 | CIO_TRACE_EVENT (2, "dissch"); | 473 | CIO_TRACE_EVENT (2, "dissch"); |
@@ -454,27 +485,9 @@ int cio_disable_subchannel(struct subchannel *sch) | |||
454 | */ | 485 | */ |
455 | return -EBUSY; | 486 | return -EBUSY; |
456 | 487 | ||
457 | for (retry = 5, ret = 0; retry > 0; retry--) { | 488 | sch->config.ena = 0; |
458 | sch->schib.pmcw.ena = 0; | 489 | ret = cio_commit_config(sch); |
459 | ret = cio_modify(sch); | 490 | |
460 | if (ret == -ENODEV) | ||
461 | break; | ||
462 | if (ret == -EBUSY) | ||
463 | /* | ||
464 | * The subchannel is busy or status pending. | ||
465 | * We'll disable when the next interrupt was delivered | ||
466 | * via the state machine. | ||
467 | */ | ||
468 | break; | ||
469 | if (ret == 0) { | ||
470 | if (cio_update_schib(sch)) { | ||
471 | ret = -ENODEV; | ||
472 | break; | ||
473 | } | ||
474 | if (!sch->schib.pmcw.ena) | ||
475 | break; | ||
476 | } | ||
477 | } | ||
478 | sprintf (dbf_txt, "ret:%d", ret); | 491 | sprintf (dbf_txt, "ret:%d", ret); |
479 | CIO_TRACE_EVENT (2, dbf_txt); | 492 | CIO_TRACE_EVENT (2, dbf_txt); |
480 | return ret; | 493 | return ret; |
@@ -817,10 +830,9 @@ cio_probe_console(void) | |||
817 | * enable console I/O-interrupt subclass | 830 | * enable console I/O-interrupt subclass |
818 | */ | 831 | */ |
819 | isc_register(CONSOLE_ISC); | 832 | isc_register(CONSOLE_ISC); |
820 | console_subchannel.schib.pmcw.isc = CONSOLE_ISC; | 833 | console_subchannel.config.isc = CONSOLE_ISC; |
821 | console_subchannel.schib.pmcw.intparm = | 834 | console_subchannel.config.intparm = (u32)(addr_t)&console_subchannel; |
822 | (u32)(addr_t)&console_subchannel; | 835 | ret = cio_commit_config(&console_subchannel); |
823 | ret = cio_modify(&console_subchannel); | ||
824 | if (ret) { | 836 | if (ret) { |
825 | isc_unregister(CONSOLE_ISC); | 837 | isc_unregister(CONSOLE_ISC); |
826 | console_subchannel_in_use = 0; | 838 | console_subchannel_in_use = 0; |
@@ -832,8 +844,8 @@ cio_probe_console(void) | |||
832 | void | 844 | void |
833 | cio_release_console(void) | 845 | cio_release_console(void) |
834 | { | 846 | { |
835 | console_subchannel.schib.pmcw.intparm = 0; | 847 | console_subchannel.config.intparm = 0; |
836 | cio_modify(&console_subchannel); | 848 | cio_commit_config(&console_subchannel); |
837 | isc_unregister(CONSOLE_ISC); | 849 | isc_unregister(CONSOLE_ISC); |
838 | console_subchannel_in_use = 0; | 850 | console_subchannel_in_use = 0; |
839 | } | 851 | } |
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index fb125efd6891..5150fba742ac 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h | |||
@@ -45,6 +45,19 @@ struct pmcw { | |||
45 | /* ... in an operand exception. */ | 45 | /* ... in an operand exception. */ |
46 | } __attribute__ ((packed)); | 46 | } __attribute__ ((packed)); |
47 | 47 | ||
48 | /* Target SCHIB configuration. */ | ||
49 | struct schib_config { | ||
50 | u64 mba; | ||
51 | u32 intparm; | ||
52 | u16 mbi; | ||
53 | u32 isc:3; | ||
54 | u32 ena:1; | ||
55 | u32 mme:2; | ||
56 | u32 mp:1; | ||
57 | u32 csense:1; | ||
58 | u32 mbfc:1; | ||
59 | } __attribute__ ((packed)); | ||
60 | |||
48 | /* | 61 | /* |
49 | * subchannel information block | 62 | * subchannel information block |
50 | */ | 63 | */ |
@@ -83,6 +96,7 @@ struct subchannel { | |||
83 | struct css_driver *driver; | 96 | struct css_driver *driver; |
84 | void *private; /* private per subchannel type data */ | 97 | void *private; /* private per subchannel type data */ |
85 | struct work_struct work; | 98 | struct work_struct work; |
99 | struct schib_config config; | ||
86 | } __attribute__ ((aligned(8))); | 100 | } __attribute__ ((aligned(8))); |
87 | 101 | ||
88 | #define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */ | 102 | #define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */ |
@@ -101,8 +115,8 @@ extern int cio_start_key (struct subchannel *, struct ccw1 *, __u8, __u8); | |||
101 | extern int cio_cancel (struct subchannel *); | 115 | extern int cio_cancel (struct subchannel *); |
102 | extern int cio_set_options (struct subchannel *, int); | 116 | extern int cio_set_options (struct subchannel *, int); |
103 | extern int cio_get_options (struct subchannel *); | 117 | extern int cio_get_options (struct subchannel *); |
104 | extern int cio_modify (struct subchannel *); | ||
105 | extern int cio_update_schib(struct subchannel *sch); | 118 | extern int cio_update_schib(struct subchannel *sch); |
119 | extern int cio_commit_config(struct subchannel *sch); | ||
106 | 120 | ||
107 | int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key); | 121 | int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key); |
108 | int cio_tm_intrg(struct subchannel *sch); | 122 | int cio_tm_intrg(struct subchannel *sch); |
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 288482b21048..6ddd02308e14 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c | |||
@@ -185,58 +185,19 @@ static inline void cmf_activate(void *area, unsigned int onoff) | |||
185 | static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, | 185 | static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, |
186 | unsigned long address) | 186 | unsigned long address) |
187 | { | 187 | { |
188 | int ret; | ||
189 | int retry; | ||
190 | struct subchannel *sch; | 188 | struct subchannel *sch; |
191 | struct schib *schib; | ||
192 | 189 | ||
193 | sch = to_subchannel(cdev->dev.parent); | 190 | 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 | if (cio_update_schib(sch)) | ||
199 | return -ENODEV; | ||
200 | schib->pmcw.mme = mme; | ||
201 | schib->pmcw.mbfc = mbfc; | ||
202 | /* address can be either a block address or a block index */ | ||
203 | if (mbfc) | ||
204 | schib->mba = address; | ||
205 | else | ||
206 | schib->pmcw.mbi = address; | ||
207 | |||
208 | /* try to submit it */ | ||
209 | switch(ret = msch_err(sch->schid, schib)) { | ||
210 | case 0: | ||
211 | break; | ||
212 | case 1: | ||
213 | case 2: /* in I/O or status pending */ | ||
214 | ret = -EBUSY; | ||
215 | break; | ||
216 | case 3: /* subchannel is no longer valid */ | ||
217 | ret = -ENODEV; | ||
218 | break; | ||
219 | default: /* msch caught an exception */ | ||
220 | ret = -EINVAL; | ||
221 | break; | ||
222 | } | ||
223 | if (cio_update_schib(sch)) | ||
224 | return -ENODEV; | ||
225 | |||
226 | if (ret) | ||
227 | break; | ||
228 | 191 | ||
229 | /* check if it worked */ | 192 | sch->config.mme = mme; |
230 | if (schib->pmcw.mme == mme && | 193 | sch->config.mbfc = mbfc; |
231 | schib->pmcw.mbfc == mbfc && | 194 | /* address can be either a block address or a block index */ |
232 | (mbfc ? (schib->mba == address) | 195 | if (mbfc) |
233 | : (schib->pmcw.mbi == address))) | 196 | sch->config.mba = address; |
234 | return 0; | 197 | else |
198 | sch->config.mbi = address; | ||
235 | 199 | ||
236 | ret = -EINVAL; | 200 | return cio_commit_config(sch); |
237 | } | ||
238 | |||
239 | return ret; | ||
240 | } | 201 | } |
241 | 202 | ||
242 | struct set_schib_struct { | 203 | struct set_schib_struct { |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 76bbb1e74c29..1b2d5149de5a 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -128,8 +128,8 @@ css_free_subchannel(struct subchannel *sch) | |||
128 | { | 128 | { |
129 | if (sch) { | 129 | if (sch) { |
130 | /* Reset intparm to zeroes. */ | 130 | /* Reset intparm to zeroes. */ |
131 | sch->schib.pmcw.intparm = 0; | 131 | sch->config.intparm = 0; |
132 | cio_modify(sch); | 132 | cio_commit_config(sch); |
133 | kfree(sch->lock); | 133 | kfree(sch->lock); |
134 | kfree(sch); | 134 | kfree(sch); |
135 | } | 135 | } |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 51e94212bf66..d3127018fb81 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -1020,8 +1020,8 @@ static void ccw_device_call_sch_unregister(struct work_struct *work) | |||
1020 | sch = to_subchannel(cdev->dev.parent); | 1020 | sch = to_subchannel(cdev->dev.parent); |
1021 | css_sch_device_unregister(sch); | 1021 | css_sch_device_unregister(sch); |
1022 | /* Reset intparm to zeroes. */ | 1022 | /* Reset intparm to zeroes. */ |
1023 | sch->schib.pmcw.intparm = 0; | 1023 | sch->config.intparm = 0; |
1024 | cio_modify(sch); | 1024 | cio_commit_config(sch); |
1025 | /* Release cdev reference for workqueue processing.*/ | 1025 | /* Release cdev reference for workqueue processing.*/ |
1026 | put_device(&cdev->dev); | 1026 | put_device(&cdev->dev); |
1027 | /* Release subchannel reference for local processing. */ | 1027 | /* Release subchannel reference for local processing. */ |
@@ -1148,8 +1148,8 @@ static void ccw_device_move_to_sch(struct work_struct *work) | |||
1148 | spin_unlock_irq(former_parent->lock); | 1148 | spin_unlock_irq(former_parent->lock); |
1149 | css_sch_device_unregister(former_parent); | 1149 | css_sch_device_unregister(former_parent); |
1150 | /* Reset intparm to zeroes. */ | 1150 | /* Reset intparm to zeroes. */ |
1151 | former_parent->schib.pmcw.intparm = 0; | 1151 | former_parent->config.intparm = 0; |
1152 | cio_modify(former_parent); | 1152 | cio_commit_config(former_parent); |
1153 | } | 1153 | } |
1154 | sch_attach_device(sch, cdev); | 1154 | sch_attach_device(sch, cdev); |
1155 | out: | 1155 | out: |
@@ -1170,6 +1170,14 @@ static void io_subchannel_irq(struct subchannel *sch) | |||
1170 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); | 1170 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); |
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | void io_subchannel_init_config(struct subchannel *sch) | ||
1174 | { | ||
1175 | memset(&sch->config, 0, sizeof(sch->config)); | ||
1176 | sch->config.csense = 1; | ||
1177 | if ((sch->lpm & (sch->lpm - 1)) != 0) | ||
1178 | sch->config.mp = 1; | ||
1179 | } | ||
1180 | |||
1173 | static void io_subchannel_init_fields(struct subchannel *sch) | 1181 | static void io_subchannel_init_fields(struct subchannel *sch) |
1174 | { | 1182 | { |
1175 | if (cio_is_console(sch->schid)) | 1183 | if (cio_is_console(sch->schid)) |
@@ -1184,16 +1192,8 @@ static void io_subchannel_init_fields(struct subchannel *sch) | |||
1184 | sch->schib.pmcw.dev, sch->schid.ssid, | 1192 | sch->schib.pmcw.dev, sch->schid.ssid, |
1185 | sch->schid.sch_no, sch->schib.pmcw.pim, | 1193 | sch->schid.sch_no, sch->schib.pmcw.pim, |
1186 | sch->schib.pmcw.pam, sch->schib.pmcw.pom); | 1194 | sch->schib.pmcw.pam, sch->schib.pmcw.pom); |
1187 | /* Initially set up some fields in the pmcw. */ | 1195 | |
1188 | sch->schib.pmcw.ena = 0; | 1196 | io_subchannel_init_config(sch); |
1189 | sch->schib.pmcw.csense = 1; /* concurrent sense */ | ||
1190 | if ((sch->lpm & (sch->lpm - 1)) != 0) | ||
1191 | sch->schib.pmcw.mp = 1; /* multipath mode */ | ||
1192 | /* clean up possible residual cmf stuff */ | ||
1193 | sch->schib.pmcw.mme = 0; | ||
1194 | sch->schib.pmcw.mbfc = 0; | ||
1195 | sch->schib.pmcw.mbi = 0; | ||
1196 | sch->schib.mba = 0; | ||
1197 | } | 1197 | } |
1198 | 1198 | ||
1199 | static void io_subchannel_do_unreg(struct work_struct *work) | 1199 | static void io_subchannel_do_unreg(struct work_struct *work) |
@@ -1203,8 +1203,8 @@ static void io_subchannel_do_unreg(struct work_struct *work) | |||
1203 | sch = container_of(work, struct subchannel, work); | 1203 | sch = container_of(work, struct subchannel, work); |
1204 | css_sch_device_unregister(sch); | 1204 | css_sch_device_unregister(sch); |
1205 | /* Reset intparm to zeroes. */ | 1205 | /* Reset intparm to zeroes. */ |
1206 | sch->schib.pmcw.intparm = 0; | 1206 | sch->config.intparm = 0; |
1207 | cio_modify(sch); | 1207 | cio_commit_config(sch); |
1208 | put_device(&sch->dev); | 1208 | put_device(&sch->dev); |
1209 | } | 1209 | } |
1210 | 1210 | ||
@@ -1680,8 +1680,8 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) | |||
1680 | spin_lock_irqsave(sch->lock, flags); | 1680 | spin_lock_irqsave(sch->lock, flags); |
1681 | 1681 | ||
1682 | /* Reset intparm to zeroes. */ | 1682 | /* Reset intparm to zeroes. */ |
1683 | sch->schib.pmcw.intparm = 0; | 1683 | sch->config.intparm = 0; |
1684 | cio_modify(sch); | 1684 | cio_commit_config(sch); |
1685 | break; | 1685 | break; |
1686 | case REPROBE: | 1686 | case REPROBE: |
1687 | ccw_device_trigger_reprobe(cdev); | 1687 | ccw_device_trigger_reprobe(cdev); |
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 104ed669db43..0f2e63ea48de 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
@@ -76,6 +76,7 @@ extern wait_queue_head_t ccw_device_init_wq; | |||
76 | extern atomic_t ccw_device_init_count; | 76 | extern atomic_t ccw_device_init_count; |
77 | 77 | ||
78 | void io_subchannel_recog_done(struct ccw_device *cdev); | 78 | void io_subchannel_recog_done(struct ccw_device *cdev); |
79 | void io_subchannel_init_config(struct subchannel *sch); | ||
79 | 80 | ||
80 | int ccw_device_cancel_halt_clear(struct ccw_device *); | 81 | int ccw_device_cancel_halt_clear(struct ccw_device *); |
81 | 82 | ||
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index e1a3786779ba..9e249675c98d 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -1026,11 +1026,12 @@ void ccw_device_trigger_reprobe(struct ccw_device *cdev) | |||
1026 | * we have before performing device selection :/ | 1026 | * we have before performing device selection :/ |
1027 | */ | 1027 | */ |
1028 | sch->lpm = sch->schib.pmcw.pam & sch->opm; | 1028 | sch->lpm = sch->schib.pmcw.pam & sch->opm; |
1029 | /* Re-set some bits in the pmcw that were lost. */ | 1029 | /* |
1030 | sch->schib.pmcw.csense = 1; | 1030 | * Use the initial configuration since we can't be shure that the old |
1031 | sch->schib.pmcw.ena = 0; | 1031 | * paths are valid. |
1032 | if ((sch->lpm & (sch->lpm - 1)) != 0) | 1032 | */ |
1033 | sch->schib.pmcw.mp = 1; | 1033 | io_subchannel_init_config(sch); |
1034 | |||
1034 | /* We should also udate ssd info, but this has to wait. */ | 1035 | /* We should also udate ssd info, but this has to wait. */ |
1035 | /* Check if this is another device which appeared on the same sch. */ | 1036 | /* Check if this is another device which appeared on the same sch. */ |
1036 | if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { | 1037 | if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { |