diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2008-12-25 07:39:13 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-12-25 07:39:10 -0500 |
commit | 13952ec12dfeea793ff83c2a96139ed57eb0b897 (patch) | |
tree | 3311df62a1794bf95f78b2c57f25f0a79dc84523 /drivers/s390/cio/device.c | |
parent | cdb912a40df8b8507ab60b3d52f9980c0ba1f44d (diff) |
[S390] cio: introduce cio_commit_config
To change the configuration of a subchannel we alter the modifiable
bits of the subchannel's schib field and issue a modify subchannel.
There can be the case that not all changes were applied -or worse-
quietly overwritten by the hardware. With the next store subchannel
we obtain the current state of the hardware but lose our target
configuration.
With this patch we introduce a subchannel_config structure which
contains the target subchannel configuration. Additionally the msch
wrapper cio_modify is replaced with cio_commit_config which
copies the desired changes to a temporary schib. msch is then
called with the temporary schib. This schib is only written back
to the subchannel if all changes were applied.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/device.c')
-rw-r--r-- | drivers/s390/cio/device.c | 36 |
1 files changed, 18 insertions, 18 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 51e94212bf66..d3127018fb81 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -1020,8 +1020,8 @@ static void ccw_device_call_sch_unregister(struct work_struct *work) | |||
1020 | sch = to_subchannel(cdev->dev.parent); | 1020 | sch = to_subchannel(cdev->dev.parent); |
1021 | css_sch_device_unregister(sch); | 1021 | css_sch_device_unregister(sch); |
1022 | /* Reset intparm to zeroes. */ | 1022 | /* Reset intparm to zeroes. */ |
1023 | sch->schib.pmcw.intparm = 0; | 1023 | sch->config.intparm = 0; |
1024 | cio_modify(sch); | 1024 | cio_commit_config(sch); |
1025 | /* Release cdev reference for workqueue processing.*/ | 1025 | /* Release cdev reference for workqueue processing.*/ |
1026 | put_device(&cdev->dev); | 1026 | put_device(&cdev->dev); |
1027 | /* Release subchannel reference for local processing. */ | 1027 | /* Release subchannel reference for local processing. */ |
@@ -1148,8 +1148,8 @@ static void ccw_device_move_to_sch(struct work_struct *work) | |||
1148 | spin_unlock_irq(former_parent->lock); | 1148 | spin_unlock_irq(former_parent->lock); |
1149 | css_sch_device_unregister(former_parent); | 1149 | css_sch_device_unregister(former_parent); |
1150 | /* Reset intparm to zeroes. */ | 1150 | /* Reset intparm to zeroes. */ |
1151 | former_parent->schib.pmcw.intparm = 0; | 1151 | former_parent->config.intparm = 0; |
1152 | cio_modify(former_parent); | 1152 | cio_commit_config(former_parent); |
1153 | } | 1153 | } |
1154 | sch_attach_device(sch, cdev); | 1154 | sch_attach_device(sch, cdev); |
1155 | out: | 1155 | out: |
@@ -1170,6 +1170,14 @@ static void io_subchannel_irq(struct subchannel *sch) | |||
1170 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); | 1170 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); |
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | void io_subchannel_init_config(struct subchannel *sch) | ||
1174 | { | ||
1175 | memset(&sch->config, 0, sizeof(sch->config)); | ||
1176 | sch->config.csense = 1; | ||
1177 | if ((sch->lpm & (sch->lpm - 1)) != 0) | ||
1178 | sch->config.mp = 1; | ||
1179 | } | ||
1180 | |||
1173 | static void io_subchannel_init_fields(struct subchannel *sch) | 1181 | static void io_subchannel_init_fields(struct subchannel *sch) |
1174 | { | 1182 | { |
1175 | if (cio_is_console(sch->schid)) | 1183 | if (cio_is_console(sch->schid)) |
@@ -1184,16 +1192,8 @@ static void io_subchannel_init_fields(struct subchannel *sch) | |||
1184 | sch->schib.pmcw.dev, sch->schid.ssid, | 1192 | sch->schib.pmcw.dev, sch->schid.ssid, |
1185 | sch->schid.sch_no, sch->schib.pmcw.pim, | 1193 | sch->schid.sch_no, sch->schib.pmcw.pim, |
1186 | sch->schib.pmcw.pam, sch->schib.pmcw.pom); | 1194 | sch->schib.pmcw.pam, sch->schib.pmcw.pom); |
1187 | /* Initially set up some fields in the pmcw. */ | 1195 | |
1188 | sch->schib.pmcw.ena = 0; | 1196 | io_subchannel_init_config(sch); |
1189 | sch->schib.pmcw.csense = 1; /* concurrent sense */ | ||
1190 | if ((sch->lpm & (sch->lpm - 1)) != 0) | ||
1191 | sch->schib.pmcw.mp = 1; /* multipath mode */ | ||
1192 | /* clean up possible residual cmf stuff */ | ||
1193 | sch->schib.pmcw.mme = 0; | ||
1194 | sch->schib.pmcw.mbfc = 0; | ||
1195 | sch->schib.pmcw.mbi = 0; | ||
1196 | sch->schib.mba = 0; | ||
1197 | } | 1197 | } |
1198 | 1198 | ||
1199 | static void io_subchannel_do_unreg(struct work_struct *work) | 1199 | static void io_subchannel_do_unreg(struct work_struct *work) |
@@ -1203,8 +1203,8 @@ static void io_subchannel_do_unreg(struct work_struct *work) | |||
1203 | sch = container_of(work, struct subchannel, work); | 1203 | sch = container_of(work, struct subchannel, work); |
1204 | css_sch_device_unregister(sch); | 1204 | css_sch_device_unregister(sch); |
1205 | /* Reset intparm to zeroes. */ | 1205 | /* Reset intparm to zeroes. */ |
1206 | sch->schib.pmcw.intparm = 0; | 1206 | sch->config.intparm = 0; |
1207 | cio_modify(sch); | 1207 | cio_commit_config(sch); |
1208 | put_device(&sch->dev); | 1208 | put_device(&sch->dev); |
1209 | } | 1209 | } |
1210 | 1210 | ||
@@ -1680,8 +1680,8 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) | |||
1680 | spin_lock_irqsave(sch->lock, flags); | 1680 | spin_lock_irqsave(sch->lock, flags); |
1681 | 1681 | ||
1682 | /* Reset intparm to zeroes. */ | 1682 | /* Reset intparm to zeroes. */ |
1683 | sch->schib.pmcw.intparm = 0; | 1683 | sch->config.intparm = 0; |
1684 | cio_modify(sch); | 1684 | cio_commit_config(sch); |
1685 | break; | 1685 | break; |
1686 | case REPROBE: | 1686 | case REPROBE: |
1687 | ccw_device_trigger_reprobe(cdev); | 1687 | ccw_device_trigger_reprobe(cdev); |