1 From: Gerald Schaefer <geraldsc@de.ibm.com>
2 Subject: cio: Properly disable not operational subchannel.
3 References: bnc#477666,LTC#51619
5 Symptom: Kernel BUG at drivers/s390/cio/device_fsm.c:1241!
6 Problem: After deferred cc=3 was received on all paths, a
7 device was set to not operational to prepare for
8 re-evaluation. An unsolicited interrupt indicating
9 that the device became accessible again triggered
10 an invalid event in the state machine (interrupt in
11 not operational state).
12 Solution: Properly disable the subchannel before setting the
13 device not operational. To be able to disable the
14 subchannel reliably, pending status needs to be
17 Acked-by: John Jolly <jjolly@suse.de>
20 drivers/s390/cio/cio.c | 19 +++++--------------
21 drivers/s390/cio/device_fsm.c | 4 ++--
22 2 files changed, 7 insertions(+), 16 deletions(-)
24 Index: linux-sles11/drivers/s390/cio/device_fsm.c
25 ===================================================================
26 --- linux-sles11.orig/drivers/s390/cio/device_fsm.c
27 +++ linux-sles11/drivers/s390/cio/device_fsm.c
28 @@ -726,7 +726,7 @@ static void ccw_device_generic_notoper(s
30 struct subchannel *sch;
32 - cdev->private->state = DEV_STATE_NOT_OPER;
33 + ccw_device_set_notoper(cdev);
34 sch = to_subchannel(cdev->dev.parent);
35 css_schedule_eval(sch->schid);
37 @@ -1048,7 +1048,7 @@ ccw_device_offline_irq(struct ccw_device
38 sch = to_subchannel(cdev->dev.parent);
40 * An interrupt in state offline means a previous disable was not
41 - * successful. Try again.
42 + * successful - should not happen, but we try to disable again.
44 cio_disable_subchannel(sch);
46 Index: linux-sles11/drivers/s390/cio/cio.c
47 ===================================================================
48 --- linux-sles11.orig/drivers/s390/cio/cio.c
49 +++ linux-sles11/drivers/s390/cio/cio.c
50 @@ -464,25 +464,16 @@ int cio_disable_subchannel(struct subcha
51 if (ccode == 3) /* Not operational. */
54 - if (scsw_actl(&sch->schib.scsw) != 0)
56 - * the disable function must not be called while there are
57 - * requests pending for completion !
61 for (retry = 5, ret = 0; retry > 0; retry--) {
62 sch->schib.pmcw.ena = 0;
63 ret = cio_modify(sch);
68 - * The subchannel is busy or status pending.
69 - * We'll disable when the next interrupt was delivered
70 - * via the state machine.
73 + if (ret == -EBUSY) {
75 + if (tsch(sch->schid, &irb) != 0)
79 stsch (sch->schid, &sch->schib);
80 if (!sch->schib.pmcw.ena)