aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/cmf.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/cmf.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/cmf.c')
-rw-r--r--drivers/s390/cio/cmf.c55
1 files changed, 8 insertions, 47 deletions
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 288482b21048..6ddd02308e14 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -185,58 +185,19 @@ static inline void cmf_activate(void *area, unsigned int onoff)
185static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, 185static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc,
186 unsigned long address) 186 unsigned long address)
187{ 187{
188 int ret;
189 int retry;
190 struct subchannel *sch; 188 struct subchannel *sch;
191 struct schib *schib;
192 189
193 sch = to_subchannel(cdev->dev.parent); 190 sch = to_subchannel(cdev->dev.parent);
194 schib = &sch->schib;
195 /* msch can silently fail, so do it again if necessary */
196 for (retry = 0; retry < 3; retry++) {
197 /* prepare schib */
198 if (cio_update_schib(sch))
199 return -ENODEV;
200 schib->pmcw.mme = mme;
201 schib->pmcw.mbfc = mbfc;
202 /* address can be either a block address or a block index */
203 if (mbfc)
204 schib->mba = address;
205 else
206 schib->pmcw.mbi = address;
207
208 /* try to submit it */
209 switch(ret = msch_err(sch->schid, schib)) {
210 case 0:
211 break;
212 case 1:
213 case 2: /* in I/O or status pending */
214 ret = -EBUSY;
215 break;
216 case 3: /* subchannel is no longer valid */
217 ret = -ENODEV;
218 break;
219 default: /* msch caught an exception */
220 ret = -EINVAL;
221 break;
222 }
223 if (cio_update_schib(sch))
224 return -ENODEV;
225
226 if (ret)
227 break;
228 191
229 /* check if it worked */ 192 sch->config.mme = mme;
230 if (schib->pmcw.mme == mme && 193 sch->config.mbfc = mbfc;
231 schib->pmcw.mbfc == mbfc && 194 /* address can be either a block address or a block index */
232 (mbfc ? (schib->mba == address) 195 if (mbfc)
233 : (schib->pmcw.mbi == address))) 196 sch->config.mba = address;
234 return 0; 197 else
198 sch->config.mbi = address;
235 199
236 ret = -EINVAL; 200 return cio_commit_config(sch);
237 }
238
239 return ret;
240} 201}
241 202
242struct set_schib_struct { 203struct set_schib_struct {