aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device.c
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2008-12-25 07:39:13 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-12-25 07:39:10 -0500
commit13952ec12dfeea793ff83c2a96139ed57eb0b897 (patch)
tree3311df62a1794bf95f78b2c57f25f0a79dc84523 /drivers/s390/cio/device.c
parentcdb912a40df8b8507ab60b3d52f9980c0ba1f44d (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.c36
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);
1155out: 1155out:
@@ -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
1173void 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
1173static void io_subchannel_init_fields(struct subchannel *sch) 1181static 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
1199static void io_subchannel_do_unreg(struct work_struct *work) 1199static 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);