aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-08-31 15:11:53 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2015-08-31 15:11:53 -0700
commit9c6a019c6edf8591e34ae9da51bac7684131d905 (patch)
treeeac9f69fc6f4dc338d6c91a4c96e2b8a2766737c /drivers/s390
parentMerge tag 'xtensa-20150830' of git://github.com/czankel/xtensa-linux (diff)
parents390/jump_label: Use %*ph to print small buffers (diff)
downloadlinux-dev-9c6a019c6edf8591e34ae9da51bac7684131d905.tar.xz
linux-dev-9c6a019c6edf8591e34ae9da51bac7684131d905.zip
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky: "The big one is support for fake NUMA, splitting a really large machine in more manageable piece improves performance in some cases, e.g. for a KVM host. The FICON Link Incident handling has been improved, this helps the operator to identify degraded or non-operational FICON connections. The save and restore of floating point and vector registers has been overhauled to allow the future use of vector registers in the kernel. A few small enhancement, magic sys-requests for the vt220 console via SCLP, some more assembler code has been converted to C, the PCI error handling is improved. And the usual cleanup and bug fixing" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (59 commits) s390/jump_label: Use %*ph to print small buffers s390/sclp_vt220: support magic sysrequests s390/ctrlchar: improve handling of magic sysrequests s390/numa: remove superfluous ARCH_WANT defines s390/3270: redraw screen on unsolicited device end s390/dcssblk: correct out of bounds array indexes s390/mm: simplify page table alloc/free code s390/pci: move debug messages to debugfs s390/nmi: initialize control register 0 earlier s390/zcrypt: use msleep() instead of mdelay() s390/hmcdrv: fix interrupt registration s390/setup: fix novx parameter s390/uaccess: remove uaccess_primary kernel parameter s390: remove unneeded sizeof(void *) comparisons s390/facilities: remove transactional-execution bits s390/numa: re-add DIE sched_domain_topology_level s390/dasd: enhance CUIR scope detection s390/dasd: fix failing path verification s390/vdso: emit a GNU hash s390/numa: make core to node mapping data dynamic ...
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/dasd_alias.c6
-rw-r--r--drivers/s390/block/dasd_eckd.c333
-rw-r--r--drivers/s390/block/dasd_eckd.h11
-rw-r--r--drivers/s390/block/dasd_int.h1
-rw-r--r--drivers/s390/block/dcssblk.c14
-rw-r--r--drivers/s390/char/con3270.c4
-rw-r--r--drivers/s390/char/ctrlchar.c16
-rw-r--r--drivers/s390/char/ctrlchar.h12
-rw-r--r--drivers/s390/char/diag_ftp.c4
-rw-r--r--drivers/s390/char/monreader.c2
-rw-r--r--drivers/s390/char/sclp.c6
-rw-r--r--drivers/s390/char/sclp_cmd.c18
-rw-r--r--drivers/s390/char/sclp_vt220.c52
-rw-r--r--drivers/s390/char/tty3270.c4
-rw-r--r--drivers/s390/cio/chsc.c165
-rw-r--r--drivers/s390/cio/device_ops.c2
-rw-r--r--drivers/s390/cio/eadm_sch.c3
-rw-r--r--drivers/s390/crypto/ap_bus.c2
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c2
-rw-r--r--drivers/s390/net/qeth_l2_main.c5
-rw-r--r--drivers/s390/net/qeth_l3_main.c5
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c2
22 files changed, 502 insertions, 167 deletions
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index ee3a6faae22a..fe07f3139bf6 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -58,7 +58,7 @@ static struct alias_server *_find_server(struct dasd_uid *uid)
&& !strncmp(pos->uid.serial, uid->serial,
sizeof(uid->serial)))
return pos;
- };
+ }
return NULL;
}
@@ -69,7 +69,7 @@ static struct alias_lcu *_find_lcu(struct alias_server *server,
list_for_each_entry(pos, &server->lculist, lcu) {
if (pos->uid.ssid == uid->ssid)
return pos;
- };
+ }
return NULL;
}
@@ -97,7 +97,7 @@ static struct alias_pav_group *_find_group(struct alias_lcu *lcu,
if (pos->uid.base_unit_addr == search_unit_addr &&
!strncmp(pos->uid.vduit, uid->vduit, sizeof(uid->vduit)))
return pos;
- };
+ }
return NULL;
}
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 6215f6455eb8..62a323539226 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1036,7 +1036,7 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
{
void *conf_data;
int conf_len, conf_data_saved;
- int rc, path_err;
+ int rc, path_err, pos;
__u8 lpm, opm;
struct dasd_eckd_private *private, path_private;
struct dasd_path *path_data;
@@ -1068,6 +1068,17 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
path_data->opm |= lpm;
continue; /* no error */
}
+ /* translate path mask to position in mask */
+ pos = 8 - ffs(lpm);
+ kfree(private->path_conf_data[pos]);
+ if ((__u8 *)private->path_conf_data[pos] ==
+ private->conf_data) {
+ private->conf_data = NULL;
+ private->conf_len = 0;
+ conf_data_saved = 0;
+ }
+ private->path_conf_data[pos] =
+ (struct dasd_conf_data *) conf_data;
/* save first valid configuration data */
if (!conf_data_saved) {
kfree(private->conf_data);
@@ -1095,7 +1106,6 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
kfree(conf_data);
continue;
}
-
if (dasd_eckd_compare_path_uid(
device, &path_private)) {
uid = &path_private.uid;
@@ -1157,9 +1167,6 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
path_data->cablepm &= ~lpm;
path_data->hpfpm &= ~lpm;
path_data->cuirpm &= ~lpm;
-
- if (conf_data != private->conf_data)
- kfree(conf_data);
}
return path_err;
@@ -1259,7 +1266,11 @@ static void do_path_verification_work(struct work_struct *work)
schedule_work(work);
return;
}
-
+ /* check if path verification already running and delay if so */
+ if (test_and_set_bit(DASD_FLAG_PATH_VERIFY, &device->flags)) {
+ schedule_work(work);
+ return;
+ }
opm = 0;
npm = 0;
ppm = 0;
@@ -1402,7 +1413,7 @@ static void do_path_verification_work(struct work_struct *work)
device->path_data.hpfpm |= hpfpm;
spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
}
-
+ clear_bit(DASD_FLAG_PATH_VERIFY, &device->flags);
dasd_put_device(device);
if (data->isglobal)
mutex_unlock(&dasd_path_verification_mutex);
@@ -1810,6 +1821,7 @@ out_err1:
static void dasd_eckd_uncheck_device(struct dasd_device *device)
{
struct dasd_eckd_private *private;
+ int i;
private = (struct dasd_eckd_private *) device->private;
dasd_alias_disconnect_device_from_lcu(device);
@@ -1818,6 +1830,15 @@ static void dasd_eckd_uncheck_device(struct dasd_device *device)
private->vdsneq = NULL;
private->gneq = NULL;
private->conf_len = 0;
+ for (i = 0; i < 8; i++) {
+ kfree(private->path_conf_data[i]);
+ if ((__u8 *)private->path_conf_data[i] ==
+ private->conf_data) {
+ private->conf_data = NULL;
+ private->conf_len = 0;
+ }
+ private->path_conf_data[i] = NULL;
+ }
kfree(private->conf_data);
private->conf_data = NULL;
}
@@ -3968,7 +3989,7 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
rc = -EFAULT;
if (copy_from_user(&usrparm, argp, sizeof(usrparm)))
goto out;
- if (is_compat_task() || sizeof(long) == 4) {
+ if (is_compat_task()) {
/* Make sure pointers are sane even on 31 bit. */
rc = -EINVAL;
if ((usrparm.psf_data >> 32) != 0)
@@ -4525,12 +4546,13 @@ static int dasd_eckd_read_message_buffer(struct dasd_device *device,
cqr->startdev = device;
cqr->memdev = device;
cqr->block = NULL;
- cqr->retries = 256;
cqr->expires = 10 * HZ;
-
- /* we need to check for messages on exactly this path */
set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags);
- cqr->lpm = lpum;
+ /* dasd_sleep_on_immediatly does not do complex error
+ * recovery so clear erp flag and set retry counter to
+ * do basic erp */
+ clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+ cqr->retries = 256;
/* Prepare for Read Subsystem Data */
prssdp = (struct dasd_psf_prssd_data *) cqr->data;
@@ -4605,10 +4627,10 @@ dasd_eckd_psf_cuir_response(struct dasd_device *device, int response,
psf_cuir->message_id = message_id;
psf_cuir->cssid = sch_id.cssid;
psf_cuir->ssid = sch_id.ssid;
-
ccw = cqr->cpaddr;
ccw->cmd_code = DASD_ECKD_CCW_PSF;
ccw->cda = (__u32)(addr_t)psf_cuir;
+ ccw->flags = CCW_FLAG_SLI;
ccw->count = sizeof(struct dasd_psf_cuir_response);
cqr->startdev = device;
@@ -4618,6 +4640,7 @@ dasd_eckd_psf_cuir_response(struct dasd_device *device, int response,
cqr->expires = 10*HZ;
cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
+ set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags);
rc = dasd_sleep_on(cqr);
@@ -4625,118 +4648,252 @@ dasd_eckd_psf_cuir_response(struct dasd_device *device, int response,
return rc;
}
-static int dasd_eckd_cuir_change_state(struct dasd_device *device, __u8 lpum)
+/*
+ * return configuration data that is referenced by record selector
+ * if a record selector is specified or per default return the
+ * conf_data pointer for the path specified by lpum
+ */
+static struct dasd_conf_data *dasd_eckd_get_ref_conf(struct dasd_device *device,
+ __u8 lpum,
+ struct dasd_cuir_message *cuir)
{
- unsigned long flags;
- __u8 tbcpm;
+ struct dasd_eckd_private *private;
+ struct dasd_conf_data *conf_data;
+ int path, pos;
- spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
- tbcpm = device->path_data.opm & ~lpum;
- if (tbcpm) {
- device->path_data.opm = tbcpm;
- device->path_data.cuirpm |= lpum;
+ private = (struct dasd_eckd_private *) device->private;
+ if (cuir->record_selector == 0)
+ goto out;
+ for (path = 0x80, pos = 0; path; path >>= 1, pos++) {
+ conf_data = private->path_conf_data[pos];
+ if (conf_data->gneq.record_selector ==
+ cuir->record_selector)
+ return conf_data;
+ }
+out:
+ return private->path_conf_data[8 - ffs(lpum)];
+}
+
+/*
+ * This function determines the scope of a reconfiguration request by
+ * analysing the path and device selection data provided in the CUIR request.
+ * Returns a path mask containing CUIR affected paths for the give device.
+ *
+ * If the CUIR request does not contain the required information return the
+ * path mask of the path the attention message for the CUIR request was reveived
+ * on.
+ */
+static int dasd_eckd_cuir_scope(struct dasd_device *device, __u8 lpum,
+ struct dasd_cuir_message *cuir)
+{
+ struct dasd_conf_data *ref_conf_data;
+ unsigned long bitmask = 0, mask = 0;
+ struct dasd_eckd_private *private;
+ struct dasd_conf_data *conf_data;
+ unsigned int pos, path;
+ char *ref_gneq, *gneq;
+ char *ref_ned, *ned;
+ int tbcpm = 0;
+
+ /* if CUIR request does not specify the scope use the path
+ the attention message was presented on */
+ if (!cuir->ned_map ||
+ !(cuir->neq_map[0] | cuir->neq_map[1] | cuir->neq_map[2]))
+ return lpum;
+
+ private = (struct dasd_eckd_private *) device->private;
+ /* get reference conf data */
+ ref_conf_data = dasd_eckd_get_ref_conf(device, lpum, cuir);
+ /* reference ned is determined by ned_map field */
+ pos = 8 - ffs(cuir->ned_map);
+ ref_ned = (char *)&ref_conf_data->neds[pos];
+ ref_gneq = (char *)&ref_conf_data->gneq;
+ /* transfer 24 bit neq_map to mask */
+ mask = cuir->neq_map[2];
+ mask |= cuir->neq_map[1] << 8;
+ mask |= cuir->neq_map[0] << 16;
+
+ for (path = 0x80; path; path >>= 1) {
+ /* initialise data per path */
+ bitmask = mask;
+ pos = 8 - ffs(path);
+ conf_data = private->path_conf_data[pos];
+ pos = 8 - ffs(cuir->ned_map);
+ ned = (char *) &conf_data->neds[pos];
+ /* compare reference ned and per path ned */
+ if (memcmp(ref_ned, ned, sizeof(*ned)) != 0)
+ continue;
+ gneq = (char *)&conf_data->gneq;
+ /* compare reference gneq and per_path gneq under
+ 24 bit mask where mask bit 0 equals byte 7 of
+ the gneq and mask bit 24 equals byte 31 */
+ while (bitmask) {
+ pos = ffs(bitmask) - 1;
+ if (memcmp(&ref_gneq[31 - pos], &gneq[31 - pos], 1)
+ != 0)
+ break;
+ clear_bit(pos, &bitmask);
+ }
+ if (bitmask)
+ continue;
+ /* device and path match the reference values
+ add path to CUIR scope */
+ tbcpm |= path;
+ }
+ return tbcpm;
+}
+
+static void dasd_eckd_cuir_notify_user(struct dasd_device *device,
+ unsigned long paths,
+ struct subchannel_id sch_id, int action)
+{
+ struct channel_path_desc *desc;
+ int pos;
+
+ while (paths) {
+ /* get position of bit in mask */
+ pos = ffs(paths) - 1;
+ /* get channel path descriptor from this position */
+ desc = ccw_device_get_chp_desc(device->cdev, 7 - pos);
+ if (action == CUIR_QUIESCE)
+ pr_warn("Service on the storage server caused path "
+ "%x.%02x to go offline", sch_id.cssid,
+ desc ? desc->chpid : 0);
+ else if (action == CUIR_RESUME)
+ pr_info("Path %x.%02x is back online after service "
+ "on the storage server", sch_id.cssid,
+ desc ? desc->chpid : 0);
+ kfree(desc);
+ clear_bit(pos, &paths);
}
- spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
- return tbcpm ? 0 : PSF_CUIR_LAST_PATH;
+}
+
+static int dasd_eckd_cuir_remove_path(struct dasd_device *device, __u8 lpum,
+ struct dasd_cuir_message *cuir)
+{
+ unsigned long tbcpm;
+
+ tbcpm = dasd_eckd_cuir_scope(device, lpum, cuir);
+ /* nothing to do if path is not in use */
+ if (!(device->path_data.opm & tbcpm))
+ return 0;
+ if (!(device->path_data.opm & ~tbcpm)) {
+ /* no path would be left if the CUIR action is taken
+ return error */
+ return -EINVAL;
+ }
+ /* remove device from operational path mask */
+ device->path_data.opm &= ~tbcpm;
+ device->path_data.cuirpm |= tbcpm;
+ return tbcpm;
}
/*
- * walk through all devices and quiesce them
- * if it is the last path return error
+ * walk through all devices and build a path mask to quiesce them
+ * return an error if the last path to a device would be removed
*
* if only part of the devices are quiesced and an error
* occurs no onlining necessary, the storage server will
* notify the already set offline devices again
*/
static int dasd_eckd_cuir_quiesce(struct dasd_device *device, __u8 lpum,
- struct channel_path_desc *desc,
- struct subchannel_id sch_id)
+ struct subchannel_id sch_id,
+ struct dasd_cuir_message *cuir)
{
struct alias_pav_group *pavgroup, *tempgroup;
struct dasd_eckd_private *private;
struct dasd_device *dev, *n;
- int rc;
+ unsigned long paths = 0;
+ unsigned long flags;
+ int tbcpm;
private = (struct dasd_eckd_private *) device->private;
- rc = 0;
-
/* active devices */
- list_for_each_entry_safe(dev, n,
- &private->lcu->active_devices,
+ list_for_each_entry_safe(dev, n, &private->lcu->active_devices,
alias_list) {
- rc = dasd_eckd_cuir_change_state(dev, lpum);
- if (rc)
- goto out;
+ spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags);
+ tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir);
+ spin_unlock_irqrestore(get_ccwdev_lock(dev->cdev), flags);
+ if (tbcpm < 0)
+ goto out_err;
+ paths |= tbcpm;
}
-
/* inactive devices */
- list_for_each_entry_safe(dev, n,
- &private->lcu->inactive_devices,
+ list_for_each_entry_safe(dev, n, &private->lcu->inactive_devices,
alias_list) {
- rc = dasd_eckd_cuir_change_state(dev, lpum);
- if (rc)
- goto out;
+ spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags);
+ tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir);
+ spin_unlock_irqrestore(get_ccwdev_lock(dev->cdev), flags);
+ if (tbcpm < 0)
+ goto out_err;
+ paths |= tbcpm;
}
-
/* devices in PAV groups */
list_for_each_entry_safe(pavgroup, tempgroup,
&private->lcu->grouplist, group) {
list_for_each_entry_safe(dev, n, &pavgroup->baselist,
alias_list) {
- rc = dasd_eckd_cuir_change_state(dev, lpum);
- if (rc)
- goto out;
+ spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags);
+ tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir);
+ spin_unlock_irqrestore(
+ get_ccwdev_lock(dev->cdev), flags);
+ if (tbcpm < 0)
+ goto out_err;
+ paths |= tbcpm;
}
list_for_each_entry_safe(dev, n, &pavgroup->aliaslist,
alias_list) {
- rc = dasd_eckd_cuir_change_state(dev, lpum);
- if (rc)
- goto out;
+ spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags);
+ tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir);
+ spin_unlock_irqrestore(
+ get_ccwdev_lock(dev->cdev), flags);
+ if (tbcpm < 0)
+ goto out_err;
+ paths |= tbcpm;
}
}
-
- pr_warn("Service on the storage server caused path %x.%02x to go offline",
- sch_id.cssid, desc ? desc->chpid : 0);
- rc = PSF_CUIR_COMPLETED;
-out:
- return rc;
+ /* notify user about all paths affected by CUIR action */
+ dasd_eckd_cuir_notify_user(device, paths, sch_id, CUIR_QUIESCE);
+ return 0;
+out_err:
+ return tbcpm;
}
static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum,
- struct channel_path_desc *desc,
- struct subchannel_id sch_id)
+ struct subchannel_id sch_id,
+ struct dasd_cuir_message *cuir)
{
struct alias_pav_group *pavgroup, *tempgroup;
struct dasd_eckd_private *private;
struct dasd_device *dev, *n;
+ unsigned long paths = 0;
+ int tbcpm;
- pr_info("Path %x.%02x is back online after service on the storage server",
- sch_id.cssid, desc ? desc->chpid : 0);
private = (struct dasd_eckd_private *) device->private;
-
/*
* the path may have been added through a generic path event before
* only trigger path verification if the path is not already in use
*/
-
list_for_each_entry_safe(dev, n,
&private->lcu->active_devices,
alias_list) {
- if (!(dev->path_data.opm & lpum)) {
- dev->path_data.tbvpm |= lpum;
+ tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
+ paths |= tbcpm;
+ if (!(dev->path_data.opm & tbcpm)) {
+ dev->path_data.tbvpm |= tbcpm;
dasd_schedule_device_bh(dev);
}
}
-
list_for_each_entry_safe(dev, n,
&private->lcu->inactive_devices,
alias_list) {
- if (!(dev->path_data.opm & lpum)) {
- dev->path_data.tbvpm |= lpum;
+ tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
+ paths |= tbcpm;
+ if (!(dev->path_data.opm & tbcpm)) {
+ dev->path_data.tbvpm |= tbcpm;
dasd_schedule_device_bh(dev);
}
}
-
/* devices in PAV groups */
list_for_each_entry_safe(pavgroup, tempgroup,
&private->lcu->grouplist,
@@ -4744,21 +4901,27 @@ static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum,
list_for_each_entry_safe(dev, n,
&pavgroup->baselist,
alias_list) {
- if (!(dev->path_data.opm & lpum)) {
- dev->path_data.tbvpm |= lpum;
+ tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
+ paths |= tbcpm;
+ if (!(dev->path_data.opm & tbcpm)) {
+ dev->path_data.tbvpm |= tbcpm;
dasd_schedule_device_bh(dev);
}
}
list_for_each_entry_safe(dev, n,
&pavgroup->aliaslist,
alias_list) {
- if (!(dev->path_data.opm & lpum)) {
- dev->path_data.tbvpm |= lpum;
+ tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
+ paths |= tbcpm;
+ if (!(dev->path_data.opm & tbcpm)) {
+ dev->path_data.tbvpm |= tbcpm;
dasd_schedule_device_bh(dev);
}
}
}
- return PSF_CUIR_COMPLETED;
+ /* notify user about all paths affected by CUIR action */
+ dasd_eckd_cuir_notify_user(device, paths, sch_id, CUIR_RESUME);
+ return 0;
}
static void dasd_eckd_handle_cuir(struct dasd_device *device, void *messages,
@@ -4768,8 +4931,12 @@ static void dasd_eckd_handle_cuir(struct dasd_device *device, void *messages,
struct channel_path_desc *desc;
struct subchannel_id sch_id;
int pos, response;
- ccw_device_get_schid(device->cdev, &sch_id);
+ DBF_DEV_EVENT(DBF_WARNING, device,
+ "CUIR request: %016llx %016llx %016llx %08x",
+ ((u64 *)cuir)[0], ((u64 *)cuir)[1], ((u64 *)cuir)[2],
+ ((u32 *)cuir)[3]);
+ ccw_device_get_schid(device->cdev, &sch_id);
/* get position of path in mask */
pos = 8 - ffs(lpum);
/* get channel path descriptor from this position */
@@ -4777,18 +4944,26 @@ static void dasd_eckd_handle_cuir(struct dasd_device *device, void *messages,
if (cuir->code == CUIR_QUIESCE) {
/* quiesce */
- response = dasd_eckd_cuir_quiesce(device, lpum, desc, sch_id);
+ if (dasd_eckd_cuir_quiesce(device, lpum, sch_id, cuir))
+ response = PSF_CUIR_LAST_PATH;
+ else
+ response = PSF_CUIR_COMPLETED;
} else if (cuir->code == CUIR_RESUME) {
/* resume */
- response = dasd_eckd_cuir_resume(device, lpum, desc, sch_id);
+ dasd_eckd_cuir_resume(device, lpum, sch_id, cuir);
+ response = PSF_CUIR_COMPLETED;
} else
response = PSF_CUIR_NOT_SUPPORTED;
- dasd_eckd_psf_cuir_response(device, response, cuir->message_id,
- desc, sch_id);
-
+ dasd_eckd_psf_cuir_response(device, response,
+ cuir->message_id, desc, sch_id);
+ DBF_DEV_EVENT(DBF_WARNING, device,
+ "CUIR response: %d on message ID %08x", response,
+ cuir->message_id);
/* free descriptor copy */
kfree(desc);
+ /* to make sure there is no attention left schedule work again */
+ device->discipline->check_attention(device, lpum);
}
static void dasd_eckd_check_attention_work(struct work_struct *work)
@@ -4800,22 +4975,18 @@ static void dasd_eckd_check_attention_work(struct work_struct *work)
data = container_of(work, struct check_attention_work_data, worker);
device = data->device;
-
messages = kzalloc(sizeof(*messages), GFP_KERNEL);
if (!messages) {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"Could not allocate attention message buffer");
goto out;
}
-
rc = dasd_eckd_read_message_buffer(device, messages, data->lpum);
if (rc)
goto out;
-
if (messages->length == ATTENTION_LENGTH_CUIR &&
messages->format == ATTENTION_FORMAT_CUIR)
dasd_eckd_handle_cuir(device, messages, data->lpum);
-
out:
dasd_put_device(device);
kfree(messages);
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index ddab7df36e25..f8f91ee652d3 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -355,7 +355,8 @@ struct dasd_gneq {
__u8 identifier:2;
__u8 reserved:6;
} __attribute__ ((packed)) flags;
- __u8 reserved[5];
+ __u8 record_selector;
+ __u8 reserved[4];
struct {
__u8 value:2;
__u8 number:6;
@@ -492,10 +493,18 @@ struct alias_pav_group {
struct dasd_device *next;
};
+struct dasd_conf_data {
+ struct dasd_ned neds[5];
+ u8 reserved[64];
+ struct dasd_gneq gneq;
+} __packed;
+
struct dasd_eckd_private {
struct dasd_eckd_characteristics rdc_data;
u8 *conf_data;
int conf_len;
+ /* per path configuration data */
+ struct dasd_conf_data *path_conf_data[8];
/* pointers to specific parts in the conf_data */
struct dasd_ned *ned;
struct dasd_sneq *sneq;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 227e3dea3155..4aed5ed70836 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -534,6 +534,7 @@ struct dasd_attention_data {
#define DASD_FLAG_SAFE_OFFLINE 10 /* safe offline processing requested*/
#define DASD_FLAG_SAFE_OFFLINE_RUNNING 11 /* safe offline running */
#define DASD_FLAG_ABORTALL 12 /* Abort all noretry requests */
+#define DASD_FLAG_PATH_VERIFY 13 /* Path verification worker running */
#define DASD_SLEEPON_START_TAG ((void *) 1)
#define DASD_SLEEPON_END_TAG ((void *) 2)
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index da212813f2d5..dff3fcb69a78 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -548,10 +548,10 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
*/
num_of_segments = 0;
for (i = 0; (i < count && (buf[i] != '\0') && (buf[i] != '\n')); i++) {
- for (j = i; (buf[j] != ':') &&
+ for (j = i; j < count &&
+ (buf[j] != ':') &&
(buf[j] != '\0') &&
- (buf[j] != '\n') &&
- j < count; j++) {
+ (buf[j] != '\n'); j++) {
local_buf[j-i] = toupper(buf[j]);
}
local_buf[j-i] = '\0';
@@ -723,7 +723,7 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch
/*
* parse input
*/
- for (i = 0; ((*(buf+i)!='\0') && (*(buf+i)!='\n') && i < count); i++) {
+ for (i = 0; (i < count && (*(buf+i)!='\0') && (*(buf+i)!='\n')); i++) {
local_buf[i] = toupper(buf[i]);
}
local_buf[i] = '\0';
@@ -904,10 +904,10 @@ dcssblk_check_params(void)
for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0');
i++) {
- for (j = i; (dcssblk_segments[j] != ',') &&
+ for (j = i; (j < DCSSBLK_PARM_LEN) &&
+ (dcssblk_segments[j] != ',') &&
(dcssblk_segments[j] != '\0') &&
- (dcssblk_segments[j] != '(') &&
- (j < DCSSBLK_PARM_LEN); j++)
+ (dcssblk_segments[j] != '('); j++)
{
buf[j-i] = dcssblk_segments[j];
}
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index 75ffe9980c3e..7c511add5aa7 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -413,6 +413,10 @@ con3270_irq(struct con3270 *cp, struct raw3270_request *rq, struct irb *irb)
else
/* Normal end. Copy residual count. */
rq->rescnt = irb->scsw.cmd.count;
+ } else if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
+ /* Interrupt without an outstanding request -> update all */
+ cp->update_flags = CON_UPDATE_ALL;
+ con3270_set_timer(cp, 1);
}
return RAW3270_IO_DONE;
}
diff --git a/drivers/s390/char/ctrlchar.c b/drivers/s390/char/ctrlchar.c
index 8de2deb176d7..f7d92584b993 100644
--- a/drivers/s390/char/ctrlchar.c
+++ b/drivers/s390/char/ctrlchar.c
@@ -14,15 +14,21 @@
#include "ctrlchar.h"
#ifdef CONFIG_MAGIC_SYSRQ
-static int ctrlchar_sysrq_key;
+static struct sysrq_work ctrlchar_sysrq;
static void
ctrlchar_handle_sysrq(struct work_struct *work)
{
- handle_sysrq(ctrlchar_sysrq_key);
+ struct sysrq_work *sysrq = container_of(work, struct sysrq_work, work);
+
+ handle_sysrq(sysrq->key);
}
-static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq);
+void schedule_sysrq_work(struct sysrq_work *sw)
+{
+ INIT_WORK(&sw->work, ctrlchar_handle_sysrq);
+ schedule_work(&sw->work);
+}
#endif
@@ -51,8 +57,8 @@ ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty)
#ifdef CONFIG_MAGIC_SYSRQ
/* racy */
if (len == 3 && buf[1] == '-') {
- ctrlchar_sysrq_key = buf[2];
- schedule_work(&ctrlchar_work);
+ ctrlchar_sysrq.key = buf[2];
+ schedule_sysrq_work(&ctrlchar_sysrq);
return CTRLCHAR_SYSRQ;
}
#endif
diff --git a/drivers/s390/char/ctrlchar.h b/drivers/s390/char/ctrlchar.h
index 1a53552f4981..59c2d6e55e55 100644
--- a/drivers/s390/char/ctrlchar.h
+++ b/drivers/s390/char/ctrlchar.h
@@ -7,6 +7,8 @@
*/
#include <linux/tty.h>
+#include <linux/sysrq.h>
+#include <linux/workqueue.h>
extern unsigned int
ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty);
@@ -17,3 +19,13 @@ ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty);
#define CTRLCHAR_SYSRQ (3 << 8)
#define CTRLCHAR_MASK (~0xffu)
+
+
+#ifdef CONFIG_MAGIC_SYSRQ
+struct sysrq_work {
+ int key;
+ struct work_struct work;
+};
+
+void schedule_sysrq_work(struct sysrq_work *sw);
+#endif
diff --git a/drivers/s390/char/diag_ftp.c b/drivers/s390/char/diag_ftp.c
index 93889632fdf9..12db8db04cdd 100644
--- a/drivers/s390/char/diag_ftp.c
+++ b/drivers/s390/char/diag_ftp.c
@@ -223,7 +223,7 @@ int diag_ftp_startup(void)
if (rc)
return rc;
- ctl_set_bit(0, 63 - 22);
+ irq_subclass_register(IRQ_SUBCLASS_SERVICE_SIGNAL);
return 0;
}
@@ -232,6 +232,6 @@ int diag_ftp_startup(void)
*/
void diag_ftp_shutdown(void)
{
- ctl_clear_bit(0, 63 - 22);
+ irq_subclass_unregister(IRQ_SUBCLASS_SERVICE_SIGNAL);
unregister_external_irq(EXT_IRQ_CP_SERVICE, diag_ftp_handler);
}
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 0da3ae3cd63b..b7d60306b0bc 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -95,7 +95,7 @@ static void dcss_mkname(char *ascii_name, char *ebcdic_name)
if (ascii_name[i] == '\0')
break;
ebcdic_name[i] = toupper(ascii_name[i]);
- };
+ }
for (; i < 8; i++)
ebcdic_name[i] = ' ';
ASCEBC(ebcdic_name, 8);
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 5e20513c0587..f58bf4c6c3ee 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -53,7 +53,7 @@ static DECLARE_COMPLETION(sclp_request_queue_flushed);
/* Number of console pages to allocate, used by sclp_con.c and sclp_vt220.c */
int sclp_console_pages = SCLP_CONSOLE_PAGES;
/* Flag to indicate if buffer pages are dropped on buffer full condition */
-int sclp_console_drop = 0;
+int sclp_console_drop = 1;
/* Number of times the console dropped buffer pages */
unsigned long sclp_console_full;
@@ -79,8 +79,8 @@ static int __init sclp_setup_console_drop(char *str)
int drop, rc;
rc = kstrtoint(str, 0, &drop);
- if (!rc && drop)
- sclp_console_drop = 1;
+ if (!rc)
+ sclp_console_drop = drop;
return 1;
}
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index e9485fbbb373..806239c2cf2f 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -25,6 +25,7 @@
#include <asm/setup.h>
#include <asm/page.h>
#include <asm/sclp.h>
+#include <asm/numa.h>
#include "sclp.h"
@@ -388,11 +389,11 @@ static struct notifier_block sclp_mem_nb = {
};
static void __init align_to_block_size(unsigned long long *start,
- unsigned long long *size)
+ unsigned long long *size,
+ unsigned long long alignment)
{
- unsigned long long start_align, size_align, alignment;
+ unsigned long long start_align, size_align;
- alignment = memory_block_size_bytes();
start_align = roundup(*start, alignment);
size_align = rounddown(*start + *size, alignment) - start_align;
@@ -404,8 +405,8 @@ static void __init align_to_block_size(unsigned long long *start,
static void __init add_memory_merged(u16 rn)
{
+ unsigned long long start, size, addr, block_size;
static u16 first_rn, num;
- unsigned long long start, size;
if (rn && first_rn && (first_rn + num == rn)) {
num++;
@@ -423,9 +424,12 @@ static void __init add_memory_merged(u16 rn)
goto skip_add;
if (memory_end_set && (start + size > memory_end))
size = memory_end - start;
- align_to_block_size(&start, &size);
- if (size)
- add_memory(0, start, size);
+ block_size = memory_block_size_bytes();
+ align_to_block_size(&start, &size, block_size);
+ if (!size)
+ goto skip_add;
+ for (addr = start; addr < start + size; addr += block_size)
+ add_memory(numa_pfn_to_nid(PFN_DOWN(addr)), addr, block_size);
skip_add:
first_rn = rn;
num = 1;
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index ae67386c03d3..68d6ee7ae504 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -12,6 +12,7 @@
#include <linux/wait.h>
#include <linux/timer.h>
#include <linux/kernel.h>
+#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
@@ -27,6 +28,7 @@
#include <asm/uaccess.h>
#include "sclp.h"
+#include "ctrlchar.h"
#define SCLP_VT220_MAJOR TTY_MAJOR
#define SCLP_VT220_MINOR 65
@@ -477,6 +479,53 @@ sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
#define SCLP_VT220_SESSION_STARTED 0x80
#define SCLP_VT220_SESSION_DATA 0x00
+#ifdef CONFIG_MAGIC_SYSRQ
+
+static int sysrq_pressed;
+static struct sysrq_work sysrq;
+
+static void sclp_vt220_reset_session(void)
+{
+ sysrq_pressed = 0;
+}
+
+static void sclp_vt220_handle_input(const char *buffer, unsigned int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ /* Handle magic sys request */
+ if (buffer[i] == ('O' ^ 0100)) { /* CTRL-O */
+ /*
+ * If pressed again, reset sysrq_pressed
+ * and flip CTRL-O character
+ */
+ sysrq_pressed = !sysrq_pressed;
+ if (sysrq_pressed)
+ continue;
+ } else if (sysrq_pressed) {
+ sysrq.key = buffer[i];
+ schedule_sysrq_work(&sysrq);
+ sysrq_pressed = 0;
+ continue;
+ }
+ tty_insert_flip_char(&sclp_vt220_port, buffer[i], 0);
+ }
+}
+
+#else
+
+static void sclp_vt220_reset_session(void)
+{
+}
+
+static void sclp_vt220_handle_input(const char *buffer, unsigned int count)
+{
+ tty_insert_flip_string(&sclp_vt220_port, buffer, count);
+}
+
+#endif
+
/*
* Called by the SCLP to report incoming event buffers.
*/
@@ -492,12 +541,13 @@ sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
switch (*buffer) {
case SCLP_VT220_SESSION_ENDED:
case SCLP_VT220_SESSION_STARTED:
+ sclp_vt220_reset_session();
break;
case SCLP_VT220_SESSION_DATA:
/* Send input to line discipline */
buffer++;
count--;
- tty_insert_flip_string(&sclp_vt220_port, buffer, count);
+ sclp_vt220_handle_input(buffer, count);
tty_flip_buffer_push(&sclp_vt220_port);
break;
}
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index e91b89dc6d1f..e96fc7fd9498 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -659,6 +659,10 @@ tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb)
else
/* Normal end. Copy residual count. */
rq->rescnt = irb->scsw.cmd.count;
+ } else if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
+ /* Interrupt without an outstanding request -> update all */
+ tp->update_flags = TTY_UPDATE_ALL;
+ tty3270_set_timer(tp, 1);
}
return RAW3270_IO_DONE;
}
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index e3bf885f4a6c..548a18916a31 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -21,6 +21,7 @@
#include <asm/chsc.h>
#include <asm/crw.h>
#include <asm/isc.h>
+#include <asm/ebcdic.h>
#include "css.h"
#include "cio.h"
@@ -272,36 +273,6 @@ static void s390_process_res_acc(struct chp_link *link)
css_schedule_reprobe();
}
-static int
-__get_chpid_from_lir(void *data)
-{
- struct lir {
- u8 iq;
- u8 ic;
- u16 sci;
- /* incident-node descriptor */
- u32 indesc[28];
- /* attached-node descriptor */
- u32 andesc[28];
- /* incident-specific information */
- u32 isinfo[28];
- } __attribute__ ((packed)) *lir;
-
- lir = data;
- if (!(lir->iq&0x80))
- /* NULL link incident record */
- return -EINVAL;
- if (!(lir->indesc[0]&0xc0000000))
- /* node descriptor not valid */
- return -EINVAL;
- if (!(lir->indesc[0]&0x10000000))
- /* don't handle device-type nodes - FIXME */
- return -EINVAL;
- /* Byte 3 contains the chpid. Could also be CTCA, but we don't care */
-
- return (u16) (lir->indesc[0]&0x000000ff);
-}
-
struct chsc_sei_nt0_area {
u8 flags;
u8 vf; /* validity flags */
@@ -341,22 +312,132 @@ struct chsc_sei {
} u;
} __packed;
+/*
+ * Node Descriptor as defined in SA22-7204, "Common I/O-Device Commands"
+ */
+
+#define ND_VALIDITY_VALID 0
+#define ND_VALIDITY_OUTDATED 1
+#define ND_VALIDITY_INVALID 2
+
+struct node_descriptor {
+ /* Flags. */
+ union {
+ struct {
+ u32 validity:3;
+ u32 reserved:5;
+ } __packed;
+ u8 byte0;
+ } __packed;
+
+ /* Node parameters. */
+ u32 params:24;
+
+ /* Node ID. */
+ char type[6];
+ char model[3];
+ char manufacturer[3];
+ char plant[2];
+ char seq[12];
+ u16 tag;
+} __packed;
+
+/*
+ * Link Incident Record as defined in SA22-7202, "ESCON I/O Interface"
+ */
+
+#define LIR_IQ_CLASS_INFO 0
+#define LIR_IQ_CLASS_DEGRADED 1
+#define LIR_IQ_CLASS_NOT_OPERATIONAL 2
+
+struct lir {
+ struct {
+ u32 null:1;
+ u32 reserved:3;
+ u32 class:2;
+ u32 reserved2:2;
+ } __packed iq;
+ u32 ic:8;
+ u32 reserved:16;
+ struct node_descriptor incident_node;
+ struct node_descriptor attached_node;
+ u8 reserved2[32];
+} __packed;
+
+#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. */
+static char *store_ebcdic(char *dest, const char *src, unsigned long len,
+ char delim)
+{
+ memcpy(dest, src, len);
+ EBCASC(dest, len);
+
+ if (delim)
+ dest[len++] = delim;
+
+ return dest + len;
+}
+
+/* Format node ID and parameters for output in LIR log message. */
+static void format_node_data(char *params, char *id, struct node_descriptor *nd)
+{
+ memset(params, 0, PARAMS_LEN);
+ memset(id, 0, NODEID_LEN);
+
+ if (nd->validity != ND_VALIDITY_VALID) {
+ strncpy(params, "n/a", PARAMS_LEN - 1);
+ strncpy(id, "n/a", NODEID_LEN - 1);
+ return;
+ }
+
+ /* PARAMS=xx,xxxxxx */
+ snprintf(params, PARAMS_LEN, "%02x,%06x", nd->byte0, nd->params);
+ /* NODEID=tttttt/mdl,mmm.ppssssssssssss,xxxx */
+ id = store_ebcdic(id, nd->type, sizeof(nd->type), '/');
+ id = store_ebcdic(id, nd->model, sizeof(nd->model), ',');
+ id = store_ebcdic(id, nd->manufacturer, sizeof(nd->manufacturer), '.');
+ id = store_ebcdic(id, nd->plant, sizeof(nd->plant), 0);
+ id = store_ebcdic(id, nd->seq, sizeof(nd->seq), ',');
+ sprintf(id, "%04X", nd->tag);
+}
+
static void chsc_process_sei_link_incident(struct chsc_sei_nt0_area *sei_area)
{
- struct chp_id chpid;
- int id;
+ struct lir *lir = (struct lir *) &sei_area->ccdf;
+ char iuparams[PARAMS_LEN], iunodeid[NODEID_LEN], auparams[PARAMS_LEN],
+ aunodeid[NODEID_LEN];
- CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x)\n",
- sei_area->rs, sei_area->rsid);
- if (sei_area->rs != 4)
+ CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x, iq=%02x)\n",
+ sei_area->rs, sei_area->rsid, sei_area->ccdf[0]);
+
+ /* Ignore NULL Link Incident Records. */
+ if (lir->iq.null)
return;
- id = __get_chpid_from_lir(sei_area->ccdf);
- if (id < 0)
- CIO_CRW_EVENT(4, "chsc: link incident - invalid LIR\n");
- else {
- chp_id_init(&chpid);
- chpid.id = id;
- chsc_chp_offline(chpid);
+
+ /* Inform user that a link requires maintenance actions because it has
+ * become degraded or not operational. Note that this log message is
+ * the primary intention behind a Link Incident Record. */
+
+ format_node_data(iuparams, iunodeid, &lir->incident_node);
+ format_node_data(auparams, aunodeid, &lir->attached_node);
+
+ switch (lir->iq.class) {
+ case LIR_IQ_CLASS_DEGRADED:
+ pr_warn("Link degraded: RS=%02x RSID=%04x IC=%02x "
+ "IUPARAMS=%s IUNODEID=%s AUPARAMS=%s AUNODEID=%s\n",
+ sei_area->rs, sei_area->rsid, lir->ic, iuparams,
+ iunodeid, auparams, aunodeid);
+ break;
+ case LIR_IQ_CLASS_NOT_OPERATIONAL:
+ pr_err("Link stopped: RS=%02x RSID=%04x IC=%02x "
+ "IUPARAMS=%s IUNODEID=%s AUPARAMS=%s AUNODEID=%s\n",
+ sei_area->rs, sei_area->rsid, lir->ic, iuparams,
+ iunodeid, auparams, aunodeid);
+ break;
+ default:
+ break;
}
}
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index f3c417943dad..6acd0b577694 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -540,7 +540,7 @@ int ccw_device_stlck(struct ccw_device *cdev)
if (rc)
goto out_unlock;
/* Perform operation. */
- cdev->private->state = DEV_STATE_STEAL_LOCK,
+ cdev->private->state = DEV_STATE_STEAL_LOCK;
ccw_device_stlck_start(cdev, &data, &buffer[0], &buffer[32]);
spin_unlock_irq(sch->lock);
/* Wait for operation to finish. */
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c
index bee8c11cd086..b3f44bc7f644 100644
--- a/drivers/s390/cio/eadm_sch.c
+++ b/drivers/s390/cio/eadm_sch.c
@@ -336,7 +336,6 @@ static int eadm_subchannel_sch_event(struct subchannel *sch, int process)
{
struct eadm_private *private;
unsigned long flags;
- int ret = 0;
spin_lock_irqsave(sch->lock, flags);
if (!device_is_registered(&sch->dev))
@@ -356,7 +355,7 @@ static int eadm_subchannel_sch_event(struct subchannel *sch, int process)
out_unlock:
spin_unlock_irqrestore(sch->lock, flags);
- return ret;
+ return 0;
}
static struct css_device_id eadm_subchannel_ids[] = {
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 559a9dcdb15d..d78b3d629d78 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -1372,7 +1372,7 @@ static int ap_probe_device_type(struct ap_device *ap_dev)
/* Wait for the test message to complete. */
for (i = 0; i < 6; i++) {
- mdelay(300);
+ msleep(300);
status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
if (status.response_code == AP_RESPONSE_NORMAL &&
psmid == 0x0102030405060708ULL)
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 899ffa19f5ec..f41852768953 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -182,7 +182,7 @@ static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
/* Wait for the test message to complete. */
for (i = 0; i < 6; i++) {
- mdelay(300);
+ msleep(300);
rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
if (rc == 0 && psmid == 0x0102030405060708ULL)
break;
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 2e65b989a9ea..a8556692f632 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -390,10 +390,8 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
return rc;
}
-static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
+static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
{
- int rc = 0;
-
QETH_DBF_TEXT(SETUP , 2, "stopcard");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
@@ -427,7 +425,6 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
qeth_clear_cmd_buffers(&card->read);
qeth_clear_cmd_buffers(&card->write);
}
- return rc;
}
static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 70eb2f61bb92..a1aaa36e9ebb 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2158,10 +2158,8 @@ static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev)
return card ;
}
-static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
+static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
{
- int rc = 0;
-
QETH_DBF_TEXT(SETUP, 2, "stopcard");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
@@ -2196,7 +2194,6 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
qeth_clear_cmd_buffers(&card->read);
qeth_clear_cmd_buffers(&card->write);
}
- return rc;
}
/*
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 21ec5e2f584c..4ac73e047c11 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -204,7 +204,7 @@ static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
break;
case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
zfcp_fsf_link_down_info_eval(req, NULL);
- };
+ }
}
static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)