aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/cmf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/cmf.c')
-rw-r--r--drivers/s390/cio/cmf.c63
1 files changed, 14 insertions, 49 deletions
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index a90b28c0be57..dc98b2c63862 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -25,6 +25,9 @@
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */ 26 */
27 27
28#define KMSG_COMPONENT "cio"
29#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
30
28#include <linux/bootmem.h> 31#include <linux/bootmem.h>
29#include <linux/device.h> 32#include <linux/device.h>
30#include <linux/init.h> 33#include <linux/init.h>
@@ -185,56 +188,19 @@ static inline void cmf_activate(void *area, unsigned int onoff)
185static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, 188static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc,
186 unsigned long address) 189 unsigned long address)
187{ 190{
188 int ret;
189 int retry;
190 struct subchannel *sch; 191 struct subchannel *sch;
191 struct schib *schib;
192 192
193 sch = to_subchannel(cdev->dev.parent); 193 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 stsch(sch->schid, schib);
199 schib->pmcw.mme = mme;
200 schib->pmcw.mbfc = mbfc;
201 /* address can be either a block address or a block index */
202 if (mbfc)
203 schib->mba = address;
204 else
205 schib->pmcw.mbi = address;
206
207 /* try to submit it */
208 switch(ret = msch_err(sch->schid, schib)) {
209 case 0:
210 break;
211 case 1:
212 case 2: /* in I/O or status pending */
213 ret = -EBUSY;
214 break;
215 case 3: /* subchannel is no longer valid */
216 ret = -ENODEV;
217 break;
218 default: /* msch caught an exception */
219 ret = -EINVAL;
220 break;
221 }
222 stsch(sch->schid, schib); /* restore the schib */
223
224 if (ret)
225 break;
226 194
227 /* check if it worked */ 195 sch->config.mme = mme;
228 if (schib->pmcw.mme == mme && 196 sch->config.mbfc = mbfc;
229 schib->pmcw.mbfc == mbfc && 197 /* address can be either a block address or a block index */
230 (mbfc ? (schib->mba == address) 198 if (mbfc)
231 : (schib->pmcw.mbi == address))) 199 sch->config.mba = address;
232 return 0; 200 else
201 sch->config.mbi = address;
233 202
234 ret = -EINVAL; 203 return cio_commit_config(sch);
235 }
236
237 return ret;
238} 204}
239 205
240struct set_schib_struct { 206struct set_schib_struct {
@@ -338,7 +304,7 @@ static int cmf_copy_block(struct ccw_device *cdev)
338 304
339 sch = to_subchannel(cdev->dev.parent); 305 sch = to_subchannel(cdev->dev.parent);
340 306
341 if (stsch(sch->schid, &sch->schib)) 307 if (cio_update_schib(sch))
342 return -ENODEV; 308 return -ENODEV;
343 309
344 if (scsw_fctl(&sch->schib.scsw) & SCSW_FCTL_START_FUNC) { 310 if (scsw_fctl(&sch->schib.scsw) & SCSW_FCTL_START_FUNC) {
@@ -1359,9 +1325,8 @@ static int __init init_cmf(void)
1359 default: 1325 default:
1360 return 1; 1326 return 1;
1361 } 1327 }
1362 1328 pr_info("Channel measurement facility initialized using format "
1363 printk(KERN_INFO "cio: Channel measurement facility using %s " 1329 "%s (mode %s)\n", format_string, detect_string);
1364 "format (%s)\n", format_string, detect_string);
1365 return 0; 1330 return 0;
1366} 1331}
1367 1332