[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>
This commit is contained in:
Родитель
47494f6a84
Коммит
edf2209692
|
@ -407,8 +407,7 @@ cio_modify (struct subchannel *sch)
|
|||
/*
|
||||
* Enable subchannel.
|
||||
*/
|
||||
int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
|
||||
u32 intparm)
|
||||
int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
|
||||
{
|
||||
char dbf_txt[15];
|
||||
int ccode;
|
||||
|
@ -426,7 +425,7 @@ int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
|
|||
|
||||
for (retry = 5, ret = 0; retry > 0; retry--) {
|
||||
sch->schib.pmcw.ena = 1;
|
||||
sch->schib.pmcw.isc = isc;
|
||||
sch->schib.pmcw.isc = sch->isc;
|
||||
sch->schib.pmcw.intparm = intparm;
|
||||
ret = cio_modify(sch);
|
||||
if (ret == -ENODEV)
|
||||
|
@ -600,6 +599,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
|
|||
else
|
||||
sch->opm = chp_get_sch_opm(sch);
|
||||
sch->lpm = sch->schib.pmcw.pam & sch->opm;
|
||||
sch->isc = 3;
|
||||
|
||||
CIO_DEBUG(KERN_INFO, 0,
|
||||
"Detected device %04x on subchannel 0.%x.%04X"
|
||||
|
@ -610,13 +610,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
|
|||
|
||||
/*
|
||||
* We now have to initially ...
|
||||
* ... set "interruption subclass"
|
||||
* ... enable "concurrent sense"
|
||||
* ... enable "multipath mode" if more than one
|
||||
* CHPID is available. This is done regardless
|
||||
* 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.ena = 0;
|
||||
if ((sch->lpm & (sch->lpm - 1)) != 0)
|
||||
|
@ -812,6 +810,7 @@ cio_probe_console(void)
|
|||
* enable console I/O-interrupt subclass 7
|
||||
*/
|
||||
ctl_set_bit(6, 24);
|
||||
console_subchannel.isc = 7;
|
||||
console_subchannel.schib.pmcw.isc = 7;
|
||||
console_subchannel.schib.pmcw.intparm =
|
||||
(u32)(addr_t)&console_subchannel;
|
||||
|
|
|
@ -74,6 +74,7 @@ struct subchannel {
|
|||
__u8 lpm; /* logical path mask */
|
||||
__u8 opm; /* operational path mask */
|
||||
struct schib schib; /* subchannel information block */
|
||||
int isc; /* desired interruption subclass */
|
||||
struct chsc_ssd_info ssd_info; /* subchannel description */
|
||||
struct device dev; /* entry in device tree */
|
||||
struct css_driver *driver;
|
||||
|
@ -85,7 +86,7 @@ struct subchannel {
|
|||
#define to_subchannel(n) container_of(n, struct subchannel, dev)
|
||||
|
||||
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_cancel (struct subchannel *);
|
||||
extern int cio_clear (struct subchannel *);
|
||||
|
|
|
@ -555,8 +555,7 @@ ccw_device_recognition(struct ccw_device *cdev)
|
|||
(cdev->private->state != DEV_STATE_BOXED))
|
||||
return -EINVAL;
|
||||
sch = to_subchannel(cdev->dev.parent);
|
||||
ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
|
||||
(u32)(addr_t)sch);
|
||||
ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
|
||||
if (ret != 0)
|
||||
/* Couldn't enable the subchannel for i/o. Sick device. */
|
||||
return ret;
|
||||
|
@ -667,8 +666,7 @@ ccw_device_online(struct ccw_device *cdev)
|
|||
sch = to_subchannel(cdev->dev.parent);
|
||||
if (css_init_done && !get_device(&cdev->dev))
|
||||
return -ENODEV;
|
||||
ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
|
||||
(u32)(addr_t)sch);
|
||||
ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
|
||||
if (ret != 0) {
|
||||
/* Couldn't enable the subchannel for i/o. Sick device. */
|
||||
if (ret == -ENODEV)
|
||||
|
@ -1048,8 +1046,7 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
|
|||
struct subchannel *sch;
|
||||
|
||||
sch = to_subchannel(cdev->dev.parent);
|
||||
if (cio_enable_subchannel(sch, sch->schib.pmcw.isc,
|
||||
(u32)(addr_t)sch) != 0)
|
||||
if (cio_enable_subchannel(sch, (u32)(addr_t)sch) != 0)
|
||||
/* Couldn't enable the subchannel for i/o. Sick device. */
|
||||
return;
|
||||
|
||||
|
@ -1082,7 +1079,6 @@ device_trigger_reprobe(struct subchannel *sch)
|
|||
*/
|
||||
sch->lpm = sch->schib.pmcw.pam & sch->opm;
|
||||
/* Re-set some bits in the pmcw that were lost. */
|
||||
sch->schib.pmcw.isc = 3;
|
||||
sch->schib.pmcw.csense = 1;
|
||||
sch->schib.pmcw.ena = 0;
|
||||
if ((sch->lpm & (sch->lpm - 1)) != 0)
|
||||
|
|
|
@ -508,7 +508,7 @@ ccw_device_stlck(struct ccw_device *cdev)
|
|||
return -ENOMEM;
|
||||
}
|
||||
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)
|
||||
goto out_unlock;
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче