diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2008-04-30 07:38:39 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-04-30 07:38:45 -0400 |
commit | edf2209692769d3e461c0351553098bc017c2caf (patch) | |
tree | 833d40fbff5e35a06fcd3c55736d20e4e82901f6 | |
parent | 47494f6a84cdae2740b62e1d86a1860df85d9bbb (diff) |
[S390] cio: Make isc handling more robust.
Introduce an ->isc field in the subchannel to store the desired
interruption subclass, since sch->schib.pmcw.isc may be overwritten
by the hardware on stsch() after machine checks.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | drivers/s390/cio/cio.c | 9 | ||||
-rw-r--r-- | drivers/s390/cio/cio.h | 3 | ||||
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 10 | ||||
-rw-r--r-- | drivers/s390/cio/device_ops.c | 2 |
4 files changed, 10 insertions, 14 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 23ffcc4768a7..08a578161306 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -407,8 +407,7 @@ cio_modify (struct subchannel *sch) | |||
407 | /* | 407 | /* |
408 | * Enable subchannel. | 408 | * Enable subchannel. |
409 | */ | 409 | */ |
410 | int cio_enable_subchannel(struct subchannel *sch, unsigned int isc, | 410 | int cio_enable_subchannel(struct subchannel *sch, u32 intparm) |
411 | u32 intparm) | ||
412 | { | 411 | { |
413 | char dbf_txt[15]; | 412 | char dbf_txt[15]; |
414 | int ccode; | 413 | int ccode; |
@@ -426,7 +425,7 @@ int cio_enable_subchannel(struct subchannel *sch, unsigned int isc, | |||
426 | 425 | ||
427 | for (retry = 5, ret = 0; retry > 0; retry--) { | 426 | for (retry = 5, ret = 0; retry > 0; retry--) { |
428 | sch->schib.pmcw.ena = 1; | 427 | sch->schib.pmcw.ena = 1; |
429 | sch->schib.pmcw.isc = isc; | 428 | sch->schib.pmcw.isc = sch->isc; |
430 | sch->schib.pmcw.intparm = intparm; | 429 | sch->schib.pmcw.intparm = intparm; |
431 | ret = cio_modify(sch); | 430 | ret = cio_modify(sch); |
432 | if (ret == -ENODEV) | 431 | if (ret == -ENODEV) |
@@ -600,6 +599,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) | |||
600 | else | 599 | else |
601 | sch->opm = chp_get_sch_opm(sch); | 600 | sch->opm = chp_get_sch_opm(sch); |
602 | sch->lpm = sch->schib.pmcw.pam & sch->opm; | 601 | sch->lpm = sch->schib.pmcw.pam & sch->opm; |
602 | sch->isc = 3; | ||
603 | 603 | ||
604 | CIO_DEBUG(KERN_INFO, 0, | 604 | CIO_DEBUG(KERN_INFO, 0, |
605 | "Detected device %04x on subchannel 0.%x.%04X" | 605 | "Detected device %04x on subchannel 0.%x.%04X" |
@@ -610,13 +610,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) | |||
610 | 610 | ||
611 | /* | 611 | /* |
612 | * We now have to initially ... | 612 | * We now have to initially ... |
613 | * ... set "interruption subclass" | ||
614 | * ... enable "concurrent sense" | 613 | * ... enable "concurrent sense" |
615 | * ... enable "multipath mode" if more than one | 614 | * ... enable "multipath mode" if more than one |
616 | * CHPID is available. This is done regardless | 615 | * CHPID is available. This is done regardless |
617 | * whether multiple paths are available for us. | 616 | * whether multiple paths are available for us. |
618 | */ | 617 | */ |
619 | sch->schib.pmcw.isc = 3; /* could be smth. else */ | ||
620 | sch->schib.pmcw.csense = 1; /* concurrent sense */ | 618 | sch->schib.pmcw.csense = 1; /* concurrent sense */ |
621 | sch->schib.pmcw.ena = 0; | 619 | sch->schib.pmcw.ena = 0; |
622 | if ((sch->lpm & (sch->lpm - 1)) != 0) | 620 | if ((sch->lpm & (sch->lpm - 1)) != 0) |
@@ -812,6 +810,7 @@ cio_probe_console(void) | |||
812 | * enable console I/O-interrupt subclass 7 | 810 | * enable console I/O-interrupt subclass 7 |
813 | */ | 811 | */ |
814 | ctl_set_bit(6, 24); | 812 | ctl_set_bit(6, 24); |
813 | console_subchannel.isc = 7; | ||
815 | console_subchannel.schib.pmcw.isc = 7; | 814 | console_subchannel.schib.pmcw.isc = 7; |
816 | console_subchannel.schib.pmcw.intparm = | 815 | console_subchannel.schib.pmcw.intparm = |
817 | (u32)(addr_t)&console_subchannel; | 816 | (u32)(addr_t)&console_subchannel; |
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index 08f2235c5a6f..3c75412904dc 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h | |||
@@ -74,6 +74,7 @@ struct subchannel { | |||
74 | __u8 lpm; /* logical path mask */ | 74 | __u8 lpm; /* logical path mask */ |
75 | __u8 opm; /* operational path mask */ | 75 | __u8 opm; /* operational path mask */ |
76 | struct schib schib; /* subchannel information block */ | 76 | struct schib schib; /* subchannel information block */ |
77 | int isc; /* desired interruption subclass */ | ||
77 | struct chsc_ssd_info ssd_info; /* subchannel description */ | 78 | struct chsc_ssd_info ssd_info; /* subchannel description */ |
78 | struct device dev; /* entry in device tree */ | 79 | struct device dev; /* entry in device tree */ |
79 | struct css_driver *driver; | 80 | struct css_driver *driver; |
@@ -85,7 +86,7 @@ struct subchannel { | |||
85 | #define to_subchannel(n) container_of(n, struct subchannel, dev) | 86 | #define to_subchannel(n) container_of(n, struct subchannel, dev) |
86 | 87 | ||
87 | extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); | 88 | extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); |
88 | extern int cio_enable_subchannel(struct subchannel *, unsigned int, u32); | 89 | extern int cio_enable_subchannel(struct subchannel *, u32); |
89 | extern int cio_disable_subchannel (struct subchannel *); | 90 | extern int cio_disable_subchannel (struct subchannel *); |
90 | extern int cio_cancel (struct subchannel *); | 91 | extern int cio_cancel (struct subchannel *); |
91 | extern int cio_clear (struct subchannel *); | 92 | extern int cio_clear (struct subchannel *); |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 4b92c84fb438..99403b0a97a7 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -555,8 +555,7 @@ ccw_device_recognition(struct ccw_device *cdev) | |||
555 | (cdev->private->state != DEV_STATE_BOXED)) | 555 | (cdev->private->state != DEV_STATE_BOXED)) |
556 | return -EINVAL; | 556 | return -EINVAL; |
557 | sch = to_subchannel(cdev->dev.parent); | 557 | sch = to_subchannel(cdev->dev.parent); |
558 | ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc, | 558 | ret = cio_enable_subchannel(sch, (u32)(addr_t)sch); |
559 | (u32)(addr_t)sch); | ||
560 | if (ret != 0) | 559 | if (ret != 0) |
561 | /* Couldn't enable the subchannel for i/o. Sick device. */ | 560 | /* Couldn't enable the subchannel for i/o. Sick device. */ |
562 | return ret; | 561 | return ret; |
@@ -667,8 +666,7 @@ ccw_device_online(struct ccw_device *cdev) | |||
667 | sch = to_subchannel(cdev->dev.parent); | 666 | sch = to_subchannel(cdev->dev.parent); |
668 | if (css_init_done && !get_device(&cdev->dev)) | 667 | if (css_init_done && !get_device(&cdev->dev)) |
669 | return -ENODEV; | 668 | return -ENODEV; |
670 | ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc, | 669 | ret = cio_enable_subchannel(sch, (u32)(addr_t)sch); |
671 | (u32)(addr_t)sch); | ||
672 | if (ret != 0) { | 670 | if (ret != 0) { |
673 | /* Couldn't enable the subchannel for i/o. Sick device. */ | 671 | /* Couldn't enable the subchannel for i/o. Sick device. */ |
674 | if (ret == -ENODEV) | 672 | if (ret == -ENODEV) |
@@ -1048,8 +1046,7 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event) | |||
1048 | struct subchannel *sch; | 1046 | struct subchannel *sch; |
1049 | 1047 | ||
1050 | sch = to_subchannel(cdev->dev.parent); | 1048 | sch = to_subchannel(cdev->dev.parent); |
1051 | if (cio_enable_subchannel(sch, sch->schib.pmcw.isc, | 1049 | if (cio_enable_subchannel(sch, (u32)(addr_t)sch) != 0) |
1052 | (u32)(addr_t)sch) != 0) | ||
1053 | /* Couldn't enable the subchannel for i/o. Sick device. */ | 1050 | /* Couldn't enable the subchannel for i/o. Sick device. */ |
1054 | return; | 1051 | return; |
1055 | 1052 | ||
@@ -1082,7 +1079,6 @@ device_trigger_reprobe(struct subchannel *sch) | |||
1082 | */ | 1079 | */ |
1083 | sch->lpm = sch->schib.pmcw.pam & sch->opm; | 1080 | sch->lpm = sch->schib.pmcw.pam & sch->opm; |
1084 | /* Re-set some bits in the pmcw that were lost. */ | 1081 | /* Re-set some bits in the pmcw that were lost. */ |
1085 | sch->schib.pmcw.isc = 3; | ||
1086 | sch->schib.pmcw.csense = 1; | 1082 | sch->schib.pmcw.csense = 1; |
1087 | sch->schib.pmcw.ena = 0; | 1083 | sch->schib.pmcw.ena = 0; |
1088 | if ((sch->lpm & (sch->lpm - 1)) != 0) | 1084 | if ((sch->lpm & (sch->lpm - 1)) != 0) |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index a1718a0aa539..f308ad55a6d5 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
@@ -508,7 +508,7 @@ ccw_device_stlck(struct ccw_device *cdev) | |||
508 | return -ENOMEM; | 508 | return -ENOMEM; |
509 | } | 509 | } |
510 | spin_lock_irqsave(sch->lock, flags); | 510 | spin_lock_irqsave(sch->lock, flags); |
511 | ret = cio_enable_subchannel(sch, 3, (u32)(addr_t)sch); | 511 | ret = cio_enable_subchannel(sch, (u32)(addr_t)sch); |
512 | if (ret) | 512 | if (ret) |
513 | goto out_unlock; | 513 | goto out_unlock; |
514 | /* | 514 | /* |