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 | /* |
