Commit edf22096 authored by Cornelia Huck's avatar Cornelia Huck Committed by Martin Schwidefsky

[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: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 47494f6a
...@@ -407,8 +407,7 @@ cio_modify (struct subchannel *sch) ...@@ -407,8 +407,7 @@ cio_modify (struct subchannel *sch)
/* /*
* Enable subchannel. * Enable subchannel.
*/ */
int cio_enable_subchannel(struct subchannel *sch, unsigned int isc, int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
u32 intparm)
{ {
char dbf_txt[15]; char dbf_txt[15];
int ccode; int ccode;
...@@ -426,7 +425,7 @@ int cio_enable_subchannel(struct subchannel *sch, unsigned int isc, ...@@ -426,7 +425,7 @@ int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
for (retry = 5, ret = 0; retry > 0; retry--) { for (retry = 5, ret = 0; retry > 0; retry--) {
sch->schib.pmcw.ena = 1; sch->schib.pmcw.ena = 1;
sch->schib.pmcw.isc = isc; sch->schib.pmcw.isc = sch->isc;
sch->schib.pmcw.intparm = intparm; sch->schib.pmcw.intparm = intparm;
ret = cio_modify(sch); ret = cio_modify(sch);
if (ret == -ENODEV) if (ret == -ENODEV)
...@@ -600,6 +599,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) ...@@ -600,6 +599,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
else else
sch->opm = chp_get_sch_opm(sch); sch->opm = chp_get_sch_opm(sch);
sch->lpm = sch->schib.pmcw.pam & sch->opm; sch->lpm = sch->schib.pmcw.pam & sch->opm;
sch->isc = 3;
CIO_DEBUG(KERN_INFO, 0, CIO_DEBUG(KERN_INFO, 0,
"Detected device %04x on subchannel 0.%x.%04X" "Detected device %04x on subchannel 0.%x.%04X"
...@@ -610,13 +610,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) ...@@ -610,13 +610,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
/* /*
* We now have to initially ... * We now have to initially ...
* ... set "interruption subclass"
* ... enable "concurrent sense" * ... enable "concurrent sense"
* ... enable "multipath mode" if more than one * ... enable "multipath mode" if more than one
* CHPID is available. This is done regardless * CHPID is available. This is done regardless
* whether multiple paths are available for us. * whether multiple paths are available for us.
*/ */
sch->schib.pmcw.isc = 3; /* could be smth. else */
sch->schib.pmcw.csense = 1; /* concurrent sense */ sch->schib.pmcw.csense = 1; /* concurrent sense */
sch->schib.pmcw.ena = 0; sch->schib.pmcw.ena = 0;
if ((sch->lpm & (sch->lpm - 1)) != 0) if ((sch->lpm & (sch->lpm - 1)) != 0)
...@@ -812,6 +810,7 @@ cio_probe_console(void) ...@@ -812,6 +810,7 @@ cio_probe_console(void)
* enable console I/O-interrupt subclass 7 * enable console I/O-interrupt subclass 7
*/ */
ctl_set_bit(6, 24); ctl_set_bit(6, 24);
console_subchannel.isc = 7;
console_subchannel.schib.pmcw.isc = 7; console_subchannel.schib.pmcw.isc = 7;
console_subchannel.schib.pmcw.intparm = console_subchannel.schib.pmcw.intparm =
(u32)(addr_t)&console_subchannel; (u32)(addr_t)&console_subchannel;
......
...@@ -74,6 +74,7 @@ struct subchannel { ...@@ -74,6 +74,7 @@ struct subchannel {
__u8 lpm; /* logical path mask */ __u8 lpm; /* logical path mask */
__u8 opm; /* operational path mask */ __u8 opm; /* operational path mask */
struct schib schib; /* subchannel information block */ struct schib schib; /* subchannel information block */
int isc; /* desired interruption subclass */
struct chsc_ssd_info ssd_info; /* subchannel description */ struct chsc_ssd_info ssd_info; /* subchannel description */
struct device dev; /* entry in device tree */ struct device dev; /* entry in device tree */
struct css_driver *driver; struct css_driver *driver;
...@@ -85,7 +86,7 @@ struct subchannel { ...@@ -85,7 +86,7 @@ struct subchannel {
#define to_subchannel(n) container_of(n, struct subchannel, dev) #define to_subchannel(n) container_of(n, struct subchannel, dev)
extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
extern int cio_enable_subchannel(struct subchannel *, unsigned int, u32); extern int cio_enable_subchannel(struct subchannel *, u32);
extern int cio_disable_subchannel (struct subchannel *); extern int cio_disable_subchannel (struct subchannel *);
extern int cio_cancel (struct subchannel *); extern int cio_cancel (struct subchannel *);
extern int cio_clear (struct subchannel *); extern int cio_clear (struct subchannel *);
......
...@@ -555,8 +555,7 @@ ccw_device_recognition(struct ccw_device *cdev) ...@@ -555,8 +555,7 @@ ccw_device_recognition(struct ccw_device *cdev)
(cdev->private->state != DEV_STATE_BOXED)) (cdev->private->state != DEV_STATE_BOXED))
return -EINVAL; return -EINVAL;
sch = to_subchannel(cdev->dev.parent); sch = to_subchannel(cdev->dev.parent);
ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc, ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
(u32)(addr_t)sch);
if (ret != 0) if (ret != 0)
/* Couldn't enable the subchannel for i/o. Sick device. */ /* Couldn't enable the subchannel for i/o. Sick device. */
return ret; return ret;
...@@ -667,8 +666,7 @@ ccw_device_online(struct ccw_device *cdev) ...@@ -667,8 +666,7 @@ ccw_device_online(struct ccw_device *cdev)
sch = to_subchannel(cdev->dev.parent); sch = to_subchannel(cdev->dev.parent);
if (css_init_done && !get_device(&cdev->dev)) if (css_init_done && !get_device(&cdev->dev))
return -ENODEV; return -ENODEV;
ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc, ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
(u32)(addr_t)sch);
if (ret != 0) { if (ret != 0) {
/* Couldn't enable the subchannel for i/o. Sick device. */ /* Couldn't enable the subchannel for i/o. Sick device. */
if (ret == -ENODEV) if (ret == -ENODEV)
...@@ -1048,8 +1046,7 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event) ...@@ -1048,8 +1046,7 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
struct subchannel *sch; struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent); sch = to_subchannel(cdev->dev.parent);
if (cio_enable_subchannel(sch, sch->schib.pmcw.isc, if (cio_enable_subchannel(sch, (u32)(addr_t)sch) != 0)
(u32)(addr_t)sch) != 0)
/* Couldn't enable the subchannel for i/o. Sick device. */ /* Couldn't enable the subchannel for i/o. Sick device. */
return; return;
...@@ -1082,7 +1079,6 @@ device_trigger_reprobe(struct subchannel *sch) ...@@ -1082,7 +1079,6 @@ device_trigger_reprobe(struct subchannel *sch)
*/ */
sch->lpm = sch->schib.pmcw.pam & sch->opm; sch->lpm = sch->schib.pmcw.pam & sch->opm;
/* Re-set some bits in the pmcw that were lost. */ /* Re-set some bits in the pmcw that were lost. */
sch->schib.pmcw.isc = 3;
sch->schib.pmcw.csense = 1; sch->schib.pmcw.csense = 1;
sch->schib.pmcw.ena = 0; sch->schib.pmcw.ena = 0;
if ((sch->lpm & (sch->lpm - 1)) != 0) if ((sch->lpm & (sch->lpm - 1)) != 0)
......
...@@ -508,7 +508,7 @@ ccw_device_stlck(struct ccw_device *cdev) ...@@ -508,7 +508,7 @@ ccw_device_stlck(struct ccw_device *cdev)
return -ENOMEM; return -ENOMEM;
} }
spin_lock_irqsave(sch->lock, flags); spin_lock_irqsave(sch->lock, flags);
ret = cio_enable_subchannel(sch, 3, (u32)(addr_t)sch); ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
if (ret) if (ret)
goto out_unlock; goto out_unlock;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment