diff options
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 2 | ||||
-rw-r--r-- | drivers/s390/cio/chp.c | 31 | ||||
-rw-r--r-- | drivers/s390/cio/chp.h | 1 | ||||
-rw-r--r-- | drivers/s390/cio/chsc.c | 31 | ||||
-rw-r--r-- | drivers/s390/cio/chsc.h | 16 | ||||
-rw-r--r-- | drivers/s390/cio/cio.c | 6 | ||||
-rw-r--r-- | drivers/s390/cio/cio.h | 2 | ||||
-rw-r--r-- | drivers/s390/cio/cmf.c | 15 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 6 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 40 | ||||
-rw-r--r-- | drivers/s390/cio/ioasm.c | 107 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 28 | ||||
-rw-r--r-- | drivers/s390/cio/scm.c | 2 |
13 files changed, 161 insertions, 126 deletions
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 66b1bdc63284..7bcf8b98b8dd 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -147,7 +147,7 @@ static ssize_t ccwgroup_online_show(struct device *dev, online = (gdev->state == CCWGROUP_ONLINE) ? 1 : 0; - return scnprintf(buf, PAGE_SIZE, "%d\n", online); + return sysfs_emit(buf, "%d\n", online); } /* diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index a07bbecba61c..cba2d048a96b 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -144,6 +144,18 @@ static ssize_t measurement_chars_read(struct file *filp, struct kobject *kobj, } static BIN_ATTR_ADMIN_RO(measurement_chars, sizeof(struct cmg_chars)); +static ssize_t measurement_chars_full_read(struct file *filp, + struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct channel_path *chp = to_channelpath(kobj_to_dev(kobj)); + + return memory_read_from_buffer(buf, count, &off, &chp->cmcb, + sizeof(chp->cmcb)); +} +static BIN_ATTR_ADMIN_RO(measurement_chars_full, sizeof(struct cmg_cmcb)); + static ssize_t chp_measurement_copy_block(void *buf, loff_t off, size_t count, struct kobject *kobj, bool extended) { @@ -201,6 +213,7 @@ static BIN_ATTR_ADMIN_RO(ext_measurement, sizeof(struct cmg_ext_entry)); static struct bin_attribute *measurement_attrs[] = { &bin_attr_measurement_chars, + &bin_attr_measurement_chars_full, &bin_attr_measurement, &bin_attr_ext_measurement, NULL, @@ -230,7 +243,7 @@ static ssize_t chp_status_show(struct device *dev, status = chp->state; mutex_unlock(&chp->lock); - return status ? sprintf(buf, "online\n") : sprintf(buf, "offline\n"); + return status ? sysfs_emit(buf, "online\n") : sysfs_emit(buf, "offline\n"); } static ssize_t chp_status_write(struct device *dev, @@ -311,7 +324,7 @@ static ssize_t chp_type_show(struct device *dev, struct device_attribute *attr, mutex_lock(&chp->lock); type = chp->desc.desc; mutex_unlock(&chp->lock); - return sprintf(buf, "%x\n", type); + return sysfs_emit(buf, "%x\n", type); } static DEVICE_ATTR(type, 0444, chp_type_show, NULL); @@ -324,8 +337,8 @@ static ssize_t chp_cmg_show(struct device *dev, struct device_attribute *attr, if (!chp) return 0; if (chp->cmg == -1) /* channel measurements not available */ - return sprintf(buf, "unknown\n"); - return sprintf(buf, "%d\n", chp->cmg); + return sysfs_emit(buf, "unknown\n"); + return sysfs_emit(buf, "%d\n", chp->cmg); } static DEVICE_ATTR(cmg, 0444, chp_cmg_show, NULL); @@ -338,8 +351,8 @@ static ssize_t chp_shared_show(struct device *dev, if (!chp) return 0; if (chp->shared == -1) /* channel measurements not available */ - return sprintf(buf, "unknown\n"); - return sprintf(buf, "%x\n", chp->shared); + return sysfs_emit(buf, "unknown\n"); + return sysfs_emit(buf, "%x\n", chp->shared); } static DEVICE_ATTR(shared, 0444, chp_shared_show, NULL); @@ -352,7 +365,7 @@ static ssize_t chp_chid_show(struct device *dev, struct device_attribute *attr, mutex_lock(&chp->lock); if (chp->desc_fmt1.flags & 0x10) - rc = sprintf(buf, "%04x\n", chp->desc_fmt1.chid); + rc = sysfs_emit(buf, "%04x\n", chp->desc_fmt1.chid); else rc = 0; mutex_unlock(&chp->lock); @@ -369,7 +382,7 @@ static ssize_t chp_chid_external_show(struct device *dev, mutex_lock(&chp->lock); if (chp->desc_fmt1.flags & 0x10) - rc = sprintf(buf, "%x\n", chp->desc_fmt1.flags & 0x8 ? 1 : 0); + rc = sysfs_emit(buf, "%x\n", chp->desc_fmt1.flags & 0x8 ? 1 : 0); else rc = 0; mutex_unlock(&chp->lock); @@ -385,7 +398,7 @@ static ssize_t chp_esc_show(struct device *dev, ssize_t rc; mutex_lock(&chp->lock); - rc = sprintf(buf, "%x\n", chp->desc_fmt1.esc); + rc = sysfs_emit(buf, "%x\n", chp->desc_fmt1.esc); mutex_unlock(&chp->lock); return rc; diff --git a/drivers/s390/cio/chp.h b/drivers/s390/cio/chp.h index a15324a43aa3..391b52a7474c 100644 --- a/drivers/s390/cio/chp.h +++ b/drivers/s390/cio/chp.h @@ -54,6 +54,7 @@ struct channel_path { int extended; unsigned long speed; struct cmg_chars cmg_chars; + struct cmg_cmcb cmcb; }; /* Return channel_path struct for given chpid. */ diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index dcc1e1c34ca2..e6462317abd0 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -376,7 +376,7 @@ struct lir { #define PARAMS_LEN 10 /* PARAMS=xx,xxxxxx */ #define NODEID_LEN 35 /* NODEID=tttttt/mdl,mmm.ppssssssssssss,xxxx */ -/* Copy EBCIDC text, convert to ASCII and optionally add delimiter. */ +/* Copy EBCDIC text, convert to ASCII and optionally add delimiter. */ static char *store_ebcdic(char *dest, const char *src, unsigned long len, char delim) { @@ -1092,19 +1092,7 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp) u32 zeroes1; struct chsc_header response; u32 zeroes2; - u32 not_valid : 1; - u32 shared : 1; - u32 extended : 1; - u32 : 21; - u32 chpid : 8; - u32 cmcv : 5; - u32 : 7; - u32 cmgp : 4; - u32 cmgq : 8; - u32 cmg : 8; - u32 : 16; - u32 cmgs : 16; - u32 data[NR_MEASUREMENT_CHARS]; + struct cmg_cmcb cmcb; } *scmc_area; chp->shared = -1; @@ -1135,15 +1123,16 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp) scmc_area->response.code); goto out; } - if (scmc_area->not_valid) + chp->cmcb = scmc_area->cmcb; + if (scmc_area->cmcb.not_valid) goto out; - chp->cmg = scmc_area->cmg; - chp->shared = scmc_area->shared; - chp->extended = scmc_area->extended; - chp->speed = scmc_get_speed(scmc_area->cmgs, scmc_area->cmgp); - chsc_initialize_cmg_chars(chp, scmc_area->cmcv, - (struct cmg_chars *) &scmc_area->data); + chp->cmg = scmc_area->cmcb.cmg; + chp->shared = scmc_area->cmcb.shared; + chp->extended = scmc_area->cmcb.extended; + chp->speed = scmc_get_speed(scmc_area->cmcb.cmgs, scmc_area->cmcb.cmgp); + chsc_initialize_cmg_chars(chp, scmc_area->cmcb.cmcv, + (struct cmg_chars *)&scmc_area->cmcb.data); out: spin_unlock_irqrestore(&chsc_page_lock, flags); return ret; diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 24cd65dbc5a7..6fe983ebf4b3 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h @@ -17,6 +17,22 @@ struct cmg_chars { u32 values[NR_MEASUREMENT_CHARS]; }; +struct cmg_cmcb { + u32 not_valid : 1; + u32 shared : 1; + u32 extended : 1; + u32 : 21; + u32 chpid : 8; + u32 cmcv : 5; + u32 : 7; + u32 cmgp : 4; + u32 cmgq : 8; + u32 cmg : 8; + u32 : 16; + u32 cmgs : 16; + u32 data[NR_MEASUREMENT_CHARS]; +}; + #define NR_MEASUREMENT_ENTRIES 8 struct cmg_entry { u32 values[NR_MEASUREMENT_ENTRIES]; diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index c32e818f06db..ad17ab0a9314 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -459,10 +459,14 @@ int cio_update_schib(struct subchannel *sch) { struct schib schib; - if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib)) + if (stsch(sch->schid, &schib)) return -ENODEV; memcpy(&sch->schib, &schib, sizeof(schib)); + + if (!css_sch_is_valid(&schib)) + return -EACCES; + return 0; } EXPORT_SYMBOL_GPL(cio_update_schib); diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index a9057a5b670a..08a5e9380e75 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -19,7 +19,7 @@ struct pmcw { u32 intparm; /* interruption parameter */ u32 qf : 1; /* qdio facility */ u32 w : 1; - u32 isc : 3; /* interruption sublass */ + u32 isc : 3; /* interruption subclass */ u32 res5 : 3; /* reserved zeros */ u32 ena : 1; /* enabled */ u32 lm : 2; /* limit mode */ diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index f80dc18e2a76..fdab760f1f28 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -46,7 +46,7 @@ /* indices for READCMB */ enum cmb_index { avg_utilization = -1, - /* basic and exended format: */ + /* basic and extended format: */ cmb_ssch_rsch_count = 0, cmb_sample_count, cmb_device_connect_time, @@ -135,7 +135,7 @@ static inline u64 time_to_nsec(u32 value) * Users are usually interested in average times, * not accumulated time. * This also helps us with atomicity problems - * when reading sinlge values. + * when reading single values. */ static inline u64 time_to_avg_nsec(u32 value, u32 count) { @@ -977,8 +977,7 @@ static struct cmb_operations cmbops_extended = { static ssize_t cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx) { - return sprintf(buf, "%lld\n", - (unsigned long long) cmf_read(to_ccwdev(dev), idx)); + return sysfs_emit(buf, "%lld\n", cmf_read(to_ccwdev(dev), idx)); } static ssize_t cmb_show_avg_sample_interval(struct device *dev, @@ -998,7 +997,7 @@ static ssize_t cmb_show_avg_sample_interval(struct device *dev, } else interval = -1; spin_unlock_irq(cdev->ccwlock); - return sprintf(buf, "%ld\n", interval); + return sysfs_emit(buf, "%ld\n", interval); } static ssize_t cmb_show_avg_utilization(struct device *dev, @@ -1007,7 +1006,7 @@ static ssize_t cmb_show_avg_utilization(struct device *dev, { unsigned long u = cmf_read(to_ccwdev(dev), avg_utilization); - return sprintf(buf, "%02lu.%01lu%%\n", u / 10, u % 10); + return sysfs_emit(buf, "%02lu.%01lu%%\n", u / 10, u % 10); } #define cmf_attr(name) \ @@ -1080,7 +1079,7 @@ static ssize_t cmb_enable_show(struct device *dev, { struct ccw_device *cdev = to_ccwdev(dev); - return sprintf(buf, "%d\n", cmf_enabled(cdev)); + return sysfs_emit(buf, "%d\n", cmf_enabled(cdev)); } static ssize_t cmb_enable_store(struct device *dev, @@ -1227,7 +1226,7 @@ int cmf_readall(struct ccw_device *cdev, struct cmbdata *data) return cmbops->readall(cdev, data); } -/* Reenable cmf when a disconnected device becomes available again. */ +/* Re-enable cmf when a disconnected device becomes available again. */ int cmf_reenable(struct ccw_device *cdev) { cmbops->reset(cdev); diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 7b59d20bf785..be78a57f9bfd 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -380,11 +380,11 @@ static ssize_t chpids_show(struct device *dev, for (chp = 0; chp < 8; chp++) { mask = 0x80 >> chp; if (ssd->path_mask & mask) - ret += sprintf(buf + ret, "%02x ", ssd->chpid[chp].id); + ret += sysfs_emit_at(buf, ret, "%02x ", ssd->chpid[chp].id); else - ret += sprintf(buf + ret, "00 "); + ret += sysfs_emit_at(buf, ret, "00 "); } - ret += sprintf(buf + ret, "\n"); + ret += sysfs_emit_at(buf, ret, "\n"); return ret; } static DEVICE_ATTR_RO(chpids); diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index b0f23242e171..fb2c07cb4d3d 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -201,10 +201,9 @@ devtype_show (struct device *dev, struct device_attribute *attr, char *buf) struct ccw_device_id *id = &(cdev->id); if (id->dev_type != 0) - return sprintf(buf, "%04x/%02x\n", - id->dev_type, id->dev_model); + return sysfs_emit(buf, "%04x/%02x\n", id->dev_type, id->dev_model); else - return sprintf(buf, "n/a\n"); + return sysfs_emit(buf, "n/a\n"); } static ssize_t @@ -213,8 +212,7 @@ cutype_show (struct device *dev, struct device_attribute *attr, char *buf) struct ccw_device *cdev = to_ccwdev(dev); struct ccw_device_id *id = &(cdev->id); - return sprintf(buf, "%04x/%02x\n", - id->cu_type, id->cu_model); + return sysfs_emit(buf, "%04x/%02x\n", id->cu_type, id->cu_model); } static ssize_t @@ -234,7 +232,7 @@ online_show (struct device *dev, struct device_attribute *attr, char *buf) { struct ccw_device *cdev = to_ccwdev(dev); - return sprintf(buf, cdev->online ? "1\n" : "0\n"); + return sysfs_emit(buf, cdev->online ? "1\n" : "0\n"); } int ccw_device_is_orphan(struct ccw_device *cdev) @@ -546,21 +544,21 @@ available_show (struct device *dev, struct device_attribute *attr, char *buf) struct subchannel *sch; if (ccw_device_is_orphan(cdev)) - return sprintf(buf, "no device\n"); + return sysfs_emit(buf, "no device\n"); switch (cdev->private->state) { case DEV_STATE_BOXED: - return sprintf(buf, "boxed\n"); + return sysfs_emit(buf, "boxed\n"); case DEV_STATE_DISCONNECTED: case DEV_STATE_DISCONNECTED_SENSE_ID: case DEV_STATE_NOT_OPER: sch = to_subchannel(dev->parent); if (!sch->lpm) - return sprintf(buf, "no path\n"); + return sysfs_emit(buf, "no path\n"); else - return sprintf(buf, "no device\n"); + return sysfs_emit(buf, "no device\n"); default: /* All other states considered fine. */ - return sprintf(buf, "good\n"); + return sysfs_emit(buf, "good\n"); } } @@ -587,7 +585,7 @@ static ssize_t vpm_show(struct device *dev, struct device_attribute *attr, { struct subchannel *sch = to_subchannel(dev); - return sprintf(buf, "%02x\n", sch->vpm); + return sysfs_emit(buf, "%02x\n", sch->vpm); } static DEVICE_ATTR_RO(devtype); @@ -1387,14 +1385,18 @@ enum io_sch_action { IO_SCH_VERIFY, IO_SCH_DISC, IO_SCH_NOP, + IO_SCH_ORPH_CDEV, }; static enum io_sch_action sch_get_action(struct subchannel *sch) { struct ccw_device *cdev; + int rc; cdev = sch_get_cdev(sch); - if (cio_update_schib(sch)) { + rc = cio_update_schib(sch); + + if (rc == -ENODEV) { /* Not operational. */ if (!cdev) return IO_SCH_UNREG; @@ -1402,6 +1404,16 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) return IO_SCH_UNREG; return IO_SCH_ORPH_UNREG; } + + /* Avoid unregistering subchannels without working device. */ + if (rc == -EACCES) { + if (!cdev) + return IO_SCH_NOP; + if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) + return IO_SCH_UNREG_CDEV; + return IO_SCH_ORPH_CDEV; + } + /* Operational. */ if (!cdev) return IO_SCH_ATTACH; @@ -1471,6 +1483,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) rc = 0; goto out_unlock; case IO_SCH_ORPH_UNREG: + case IO_SCH_ORPH_CDEV: case IO_SCH_ORPH_ATTACH: ccw_device_set_disconnected(cdev); break; @@ -1502,6 +1515,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) /* Handle attached ccw device. */ switch (action) { case IO_SCH_ORPH_UNREG: + case IO_SCH_ORPH_CDEV: case IO_SCH_ORPH_ATTACH: /* Move ccw device to orphanage. */ rc = ccw_device_move_to_orph(cdev); diff --git a/drivers/s390/cio/ioasm.c b/drivers/s390/cio/ioasm.c index acf1edd36549..5ff1e51cddf3 100644 --- a/drivers/s390/cio/ioasm.c +++ b/drivers/s390/cio/ioasm.c @@ -8,6 +8,7 @@ #include <asm/asm-extable.h> #include <asm/chpid.h> #include <asm/schid.h> +#include <asm/asm.h> #include <asm/crw.h> #include "ioasm.h" @@ -18,19 +19,20 @@ static inline int __stsch(struct subchannel_id schid, struct schib *addr) { unsigned long r1 = *(unsigned int *)&schid; - int ccode = -EIO; + int ccode, exception; + exception = 1; asm volatile( " lgr 1,%[r1]\n" " stsch %[addr]\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+&d" (ccode), [addr] "=Q" (*addr) + : CC_OUT(cc, ccode), [addr] "=Q" (*addr), [exc] "+d" (exception) : [r1] "d" (r1) - : "cc", "1"); - return ccode; + : CC_CLOBBER_LIST("1")); + return exception ? -EIO : CC_TRANSFORM(ccode); } int stsch(struct subchannel_id schid, struct schib *addr) @@ -47,19 +49,20 @@ EXPORT_SYMBOL(stsch); static inline int __msch(struct subchannel_id schid, struct schib *addr) { unsigned long r1 = *(unsigned int *)&schid; - int ccode = -EIO; + int ccode, exception; + exception = 1; asm volatile( " lgr 1,%[r1]\n" " msch %[addr]\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+&d" (ccode) + : CC_OUT(cc, ccode), [exc] "+d" (exception) : [r1] "d" (r1), [addr] "Q" (*addr) - : "cc", "1"); - return ccode; + : CC_CLOBBER_LIST("1")); + return exception ? -EIO : CC_TRANSFORM(ccode); } int msch(struct subchannel_id schid, struct schib *addr) @@ -80,12 +83,11 @@ static inline int __tsch(struct subchannel_id schid, struct irb *addr) asm volatile( " lgr 1,%[r1]\n" " tsch %[addr]\n" - " ipm %[cc]\n" - " srl %[cc],28" - : [cc] "=&d" (ccode), [addr] "=Q" (*addr) + CC_IPM(cc) + : CC_OUT(cc, ccode), [addr] "=Q" (*addr) : [r1] "d" (r1) - : "cc", "1"); - return ccode; + : CC_CLOBBER_LIST("1")); + return CC_TRANSFORM(ccode); } int tsch(struct subchannel_id schid, struct irb *addr) @@ -101,19 +103,20 @@ int tsch(struct subchannel_id schid, struct irb *addr) static inline int __ssch(struct subchannel_id schid, union orb *addr) { unsigned long r1 = *(unsigned int *)&schid; - int ccode = -EIO; + int ccode, exception; + exception = 1; asm volatile( " lgr 1,%[r1]\n" " ssch %[addr]\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+&d" (ccode) + : CC_OUT(cc, ccode), [exc] "+d" (exception) : [r1] "d" (r1), [addr] "Q" (*addr) - : "cc", "memory", "1"); - return ccode; + : CC_CLOBBER_LIST("memory", "1")); + return CC_TRANSFORM(ccode); } int ssch(struct subchannel_id schid, union orb *addr) @@ -135,12 +138,11 @@ static inline int __csch(struct subchannel_id schid) asm volatile( " lgr 1,%[r1]\n" " csch\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=&d" (ccode) + CC_IPM(cc) + : CC_OUT(cc, ccode) : [r1] "d" (r1) - : "cc", "1"); - return ccode; + : CC_CLOBBER_LIST("1")); + return CC_TRANSFORM(ccode); } int csch(struct subchannel_id schid) @@ -160,11 +162,11 @@ int tpi(struct tpi_info *addr) asm volatile( " tpi %[addr]\n" - " ipm %[cc]\n" - " srl %[cc],28" - : [cc] "=&d" (ccode), [addr] "=Q" (*addr) + CC_IPM(cc) + : CC_OUT(cc, ccode), [addr] "=Q" (*addr) : - : "cc"); + : CC_CLOBBER); + ccode = CC_TRANSFORM(ccode); trace_s390_cio_tpi(addr, ccode); return ccode; @@ -173,17 +175,19 @@ int tpi(struct tpi_info *addr) int chsc(void *chsc_area) { typedef struct { char _[4096]; } addr_type; - int cc = -EIO; + int cc, exception; + exception = 1; asm volatile( " .insn rre,0xb25f0000,%[chsc_area],0\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+&d" (cc), "+m" (*(addr_type *)chsc_area) + : CC_OUT(cc, cc), "+m" (*(addr_type *)chsc_area), [exc] "+d" (exception) : [chsc_area] "d" (chsc_area) - : "cc"); + : CC_CLOBBER); + cc = exception ? -EIO : CC_TRANSFORM(cc); trace_s390_cio_chsc(chsc_area, cc); return cc; @@ -198,12 +202,11 @@ static inline int __rsch(struct subchannel_id schid) asm volatile( " lgr 1,%[r1]\n" " rsch\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=&d" (ccode) + CC_IPM(cc) + : CC_OUT(cc, ccode) : [r1] "d" (r1) - : "cc", "memory", "1"); - return ccode; + : CC_CLOBBER_LIST("memory", "1")); + return CC_TRANSFORM(ccode); } int rsch(struct subchannel_id schid) @@ -224,12 +227,11 @@ static inline int __hsch(struct subchannel_id schid) asm volatile( " lgr 1,%[r1]\n" " hsch\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=&d" (ccode) + CC_IPM(cc) + : CC_OUT(cc, ccode) : [r1] "d" (r1) - : "cc", "1"); - return ccode; + : CC_CLOBBER_LIST("1")); + return CC_TRANSFORM(ccode); } int hsch(struct subchannel_id schid) @@ -256,7 +258,7 @@ static inline int __xsch(struct subchannel_id schid) : [cc] "=&d" (ccode) : [r1] "d" (r1) : "cc", "1"); - return ccode; + return CC_TRANSFORM(ccode); } int xsch(struct subchannel_id schid) @@ -275,12 +277,11 @@ static inline int __stcrw(struct crw *crw) asm volatile( " stcrw %[crw]\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=&d" (ccode), [crw] "=Q" (*crw) + CC_IPM(cc) + : CC_OUT(cc, ccode), [crw] "=Q" (*crw) : - : "cc"); - return ccode; + : CC_CLOBBER); + return CC_TRANSFORM(ccode); } static inline int _stcrw(struct crw *crw) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index b711bb17f9da..07e82816b77a 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -17,6 +17,7 @@ #include <linux/atomic.h> #include <asm/debug.h> #include <asm/qdio.h> +#include <asm/asm.h> #include <asm/ipl.h> #include "cio.h" @@ -42,13 +43,12 @@ static inline int do_siga_sync(unsigned long schid, " lgr 2,%[out]\n" " lgr 3,%[in]\n" " siga 0\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=&d" (cc) + CC_IPM(cc) + : CC_OUT(cc, cc) : [fc] "d" (fc), [schid] "d" (schid), [out] "d" (out_mask), [in] "d" (in_mask) - : "cc", "0", "1", "2", "3"); - return cc; + : CC_CLOBBER_LIST("0", "1", "2", "3")); + return CC_TRANSFORM(cc); } static inline int do_siga_input(unsigned long schid, unsigned long mask, @@ -61,12 +61,11 @@ static inline int do_siga_input(unsigned long schid, unsigned long mask, " lgr 1,%[schid]\n" " lgr 2,%[mask]\n" " siga 0\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=&d" (cc) + CC_IPM(cc) + : CC_OUT(cc, cc) : [fc] "d" (fc), [schid] "d" (schid), [mask] "d" (mask) - : "cc", "0", "1", "2"); - return cc; + : CC_CLOBBER_LIST("0", "1", "2")); + return CC_TRANSFORM(cc); } /** @@ -93,13 +92,12 @@ static inline int do_siga_output(unsigned long schid, unsigned long mask, " lgr 3,%[aob]\n" " siga 0\n" " lgr %[fc],0\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=&d" (cc), [fc] "+&d" (fc) + CC_IPM(cc) + : CC_OUT(cc, cc), [fc] "+&d" (fc) : [schid] "d" (schid), [mask] "d" (mask), [aob] "d" (aob) - : "cc", "0", "1", "2", "3"); + : CC_CLOBBER_LIST("0", "1", "2", "3")); *bb = fc >> 31; - return cc; + return CC_TRANSFORM(cc); } /** diff --git a/drivers/s390/cio/scm.c b/drivers/s390/cio/scm.c index c7894d61306d..a0825e372d42 100644 --- a/drivers/s390/cio/scm.c +++ b/drivers/s390/cio/scm.c @@ -91,7 +91,7 @@ static ssize_t show_##name(struct device *dev, \ int ret; \ \ device_lock(dev); \ - ret = sprintf(buf, "%u\n", scmdev->attrs.name); \ + ret = sysfs_emit(buf, "%u\n", scmdev->attrs.name); \ device_unlock(dev); \ \ return ret; \ |