aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2008-04-30 07:38:39 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-04-30 07:38:45 -0400
commitedf2209692769d3e461c0351553098bc017c2caf (patch)
tree833d40fbff5e35a06fcd3c55736d20e4e82901f6
parent47494f6a84cdae2740b62e1d86a1860df85d9bbb (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.c9
-rw-r--r--drivers/s390/cio/cio.h3
-rw-r--r--drivers/s390/cio/device_fsm.c10
-rw-r--r--drivers/s390/cio/device_ops.c2
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 */
410int cio_enable_subchannel(struct subchannel *sch, unsigned int isc, 410int 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
87extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); 88extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
88extern int cio_enable_subchannel(struct subchannel *, unsigned int, u32); 89extern int cio_enable_subchannel(struct subchannel *, u32);
89extern int cio_disable_subchannel (struct subchannel *); 90extern int cio_disable_subchannel (struct subchannel *);
90extern int cio_cancel (struct subchannel *); 91extern int cio_cancel (struct subchannel *);
91extern int cio_clear (struct subchannel *); 92extern 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 /*