summaryrefslogtreecommitdiff
path: root/drivers/s390/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/con3270.c21
-rw-r--r--drivers/s390/char/diag_ftp.c3
-rw-r--r--drivers/s390/char/fs3270.c7
-rw-r--r--drivers/s390/char/hmcdrv_cache.c3
-rw-r--r--drivers/s390/char/hmcdrv_dev.c3
-rw-r--r--drivers/s390/char/hmcdrv_ftp.c3
-rw-r--r--drivers/s390/char/hmcdrv_mod.c3
-rw-r--r--drivers/s390/char/monreader.c3
-rw-r--r--drivers/s390/char/monwriter.c3
-rw-r--r--drivers/s390/char/sclp_ap.c3
-rw-r--r--drivers/s390/char/sclp_cmd.c3
-rw-r--r--drivers/s390/char/sclp_config.c3
-rw-r--r--drivers/s390/char/sclp_cpi_sys.c3
-rw-r--r--drivers/s390/char/sclp_ctl.c12
-rw-r--r--drivers/s390/char/sclp_early.c3
-rw-r--r--drivers/s390/char/sclp_ftp.c3
-rw-r--r--drivers/s390/char/sclp_mem.c292
-rw-r--r--drivers/s390/char/sclp_ocf.c3
-rw-r--r--drivers/s390/char/sclp_pci.c3
-rw-r--r--drivers/s390/char/sclp_sd.c3
-rw-r--r--drivers/s390/char/sclp_sdias.c3
-rw-r--r--drivers/s390/char/tape.h21
-rw-r--r--drivers/s390/char/tape_34xx.c31
-rw-r--r--drivers/s390/char/tape_3590.c92
-rw-r--r--drivers/s390/char/tape_char.c142
-rw-r--r--drivers/s390/char/tape_class.c3
-rw-r--r--drivers/s390/char/tape_core.c38
-rw-r--r--drivers/s390/char/tape_proc.c3
-rw-r--r--drivers/s390/char/tape_std.c83
-rw-r--r--drivers/s390/char/tape_std.h9
-rw-r--r--drivers/s390/char/vmcp.c7
-rw-r--r--drivers/s390/char/vmlogrdr.c3
-rw-r--r--drivers/s390/char/vmur.c3
-rw-r--r--drivers/s390/char/zcore.c3
34 files changed, 376 insertions, 445 deletions
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index a367f95c7c53..4a7c084e68a6 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -21,7 +21,6 @@
#include <linux/reboot.h>
#include <linux/slab.h>
#include <linux/memblock.h>
-#include <linux/compat.h>
#include <asm/machine.h>
#include <asm/ccwdev.h>
@@ -1662,7 +1661,7 @@ static void tty3270_escape_sequence(struct tty3270 *tp, u8 ch)
else if (tp->esc_par[0] == 6) { /* Cursor report. */
char buf[40];
- sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1);
+ scnprintf(buf, sizeof(buf), "\033[%d;%dR", tp->cy + 1, tp->cx + 1);
kbd_puts_queue(&tp->port, buf);
}
return;
@@ -1947,21 +1946,6 @@ static int tty3270_ioctl(struct tty_struct *tty, unsigned int cmd,
return kbd_ioctl(tp->kbd, cmd, arg);
}
-#ifdef CONFIG_COMPAT
-static long tty3270_compat_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg)
-{
- struct tty3270 *tp;
-
- tp = tty->driver_data;
- if (!tp)
- return -ENODEV;
- if (tty_io_error(tty))
- return -EIO;
- return kbd_ioctl(tp->kbd, cmd, (unsigned long)compat_ptr(arg));
-}
-#endif
-
static const struct tty_operations tty3270_ops = {
.install = tty3270_install,
.cleanup = tty3270_cleanup,
@@ -1976,9 +1960,6 @@ static const struct tty_operations tty3270_ops = {
.hangup = tty3270_hangup,
.wait_until_sent = tty3270_wait_until_sent,
.ioctl = tty3270_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = tty3270_compat_ioctl,
-#endif
.set_termios = tty3270_set_termios
};
diff --git a/drivers/s390/char/diag_ftp.c b/drivers/s390/char/diag_ftp.c
index f41b39c9d267..a1e110c96f74 100644
--- a/drivers/s390/char/diag_ftp.c
+++ b/drivers/s390/char/diag_ftp.c
@@ -7,8 +7,7 @@
*
*/
-#define KMSG_COMPONENT "hmcdrv"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "hmcdrv: " fmt
#include <linux/kernel.h>
#include <linux/mm.h>
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index cfe7efd5b5da..73555dbe30d0 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -12,7 +12,6 @@
#include <linux/console.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/compat.h>
#include <linux/sched/signal.h>
#include <linux/module.h>
#include <linux/list.h>
@@ -330,10 +329,7 @@ static long fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
fp = filp->private_data;
if (!fp)
return -ENODEV;
- if (is_compat_task())
- argp = compat_ptr(arg);
- else
- argp = (char __user *)arg;
+ argp = (char __user *)arg;
rc = 0;
mutex_lock(&fs3270_mutex);
switch (cmd) {
@@ -512,7 +508,6 @@ static const struct file_operations fs3270_fops = {
.read = fs3270_read, /* read */
.write = fs3270_write, /* write */
.unlocked_ioctl = fs3270_ioctl, /* ioctl */
- .compat_ioctl = fs3270_ioctl, /* ioctl */
.open = fs3270_open, /* open */
.release = fs3270_close, /* release */
};
diff --git a/drivers/s390/char/hmcdrv_cache.c b/drivers/s390/char/hmcdrv_cache.c
index 43df27ceec11..85fb689594ca 100644
--- a/drivers/s390/char/hmcdrv_cache.c
+++ b/drivers/s390/char/hmcdrv_cache.c
@@ -7,8 +7,7 @@
*
*/
-#define KMSG_COMPONENT "hmcdrv"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "hmcdrv: " fmt
#include <linux/kernel.h>
#include <linux/mm.h>
diff --git a/drivers/s390/char/hmcdrv_dev.c b/drivers/s390/char/hmcdrv_dev.c
index b26fcf6849f2..04b938c5357f 100644
--- a/drivers/s390/char/hmcdrv_dev.c
+++ b/drivers/s390/char/hmcdrv_dev.c
@@ -14,8 +14,7 @@
* end read() the response.
*/
-#define KMSG_COMPONENT "hmcdrv"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "hmcdrv: " fmt
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/s390/char/hmcdrv_ftp.c b/drivers/s390/char/hmcdrv_ftp.c
index 4e3c7ec6749b..3312b2ac00a9 100644
--- a/drivers/s390/char/hmcdrv_ftp.c
+++ b/drivers/s390/char/hmcdrv_ftp.c
@@ -6,8 +6,7 @@
* Author(s): Ralf Hoppe (rhoppe@de.ibm.com)
*/
-#define KMSG_COMPONENT "hmcdrv"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "hmcdrv: " fmt
#include <linux/kernel.h>
#include <linux/slab.h>
diff --git a/drivers/s390/char/hmcdrv_mod.c b/drivers/s390/char/hmcdrv_mod.c
index 1447d0887225..b1cc5ba9fed8 100644
--- a/drivers/s390/char/hmcdrv_mod.c
+++ b/drivers/s390/char/hmcdrv_mod.c
@@ -6,8 +6,7 @@
* Author(s): Ralf Hoppe (rhoppe@de.ibm.com)
*/
-#define KMSG_COMPONENT "hmcdrv"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "hmcdrv: " fmt
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 2d9886651d9b..3d84f84b4cbd 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -7,8 +7,7 @@
* Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
*/
-#define KMSG_COMPONENT "monreader"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "monreader: " fmt
#include <linux/module.h>
#include <linux/moduleparam.h>
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 0fab1f025a94..cf2e51061422 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -7,8 +7,7 @@
* Author(s): Melissa Howland <Melissa.Howland@us.ibm.com>
*/
-#define KMSG_COMPONENT "monwriter"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "monwriter: " fmt
#include <linux/module.h>
#include <linux/moduleparam.h>
diff --git a/drivers/s390/char/sclp_ap.c b/drivers/s390/char/sclp_ap.c
index 0dd1ca712795..18bb018b4e0c 100644
--- a/drivers/s390/char/sclp_ap.c
+++ b/drivers/s390/char/sclp_ap.c
@@ -4,8 +4,7 @@
*
* Copyright IBM Corp. 2020
*/
-#define KMSG_COMPONENT "sclp_cmd"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "sclp_cmd: " fmt
#include <linux/export.h>
#include <linux/slab.h>
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 3480198eac02..be4730936f5c 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -5,8 +5,7 @@
* Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
*/
-#define KMSG_COMPONENT "sclp_cmd"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "sclp_cmd: " fmt
#include <linux/completion.h>
#include <linux/err.h>
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index 356d26a09af0..9cfbe3fc3dca 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -3,8 +3,7 @@
* Copyright IBM Corp. 2007
*/
-#define KMSG_COMPONENT "sclp_config"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "sclp_config: " fmt
#include <linux/init.h>
#include <linux/errno.h>
diff --git a/drivers/s390/char/sclp_cpi_sys.c b/drivers/s390/char/sclp_cpi_sys.c
index d8f91aab11e8..8e1636bcf8b5 100644
--- a/drivers/s390/char/sclp_cpi_sys.c
+++ b/drivers/s390/char/sclp_cpi_sys.c
@@ -7,8 +7,7 @@
* Michael Ernst <mernst@de.ibm.com>
*/
-#define KMSG_COMPONENT "sclp_cpi"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "sclp_cpi: " fmt
#include <linux/kernel.h>
#include <linux/init.h>
diff --git a/drivers/s390/char/sclp_ctl.c b/drivers/s390/char/sclp_ctl.c
index dd6051602070..e23a97359286 100644
--- a/drivers/s390/char/sclp_ctl.c
+++ b/drivers/s390/char/sclp_ctl.c
@@ -7,7 +7,6 @@
* Author: Michael Holzheu <holzheu@linux.vnet.ibm.com>
*/
-#include <linux/compat.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/gfp.h>
@@ -43,10 +42,7 @@ static int sclp_ctl_cmdw_supported(unsigned int cmdw)
static void __user *u64_to_uptr(u64 value)
{
- if (is_compat_task())
- return compat_ptr(value);
- else
- return (void __user *)(unsigned long)value;
+ return (void __user *)(unsigned long)value;
}
/*
@@ -95,10 +91,7 @@ static long sclp_ctl_ioctl(struct file *filp, unsigned int cmd,
{
void __user *argp;
- if (is_compat_task())
- argp = compat_ptr(arg);
- else
- argp = (void __user *) arg;
+ argp = (void __user *)arg;
switch (cmd) {
case SCLP_CTL_SCCB:
return sclp_ctl_ioctl_sccb(argp);
@@ -114,7 +107,6 @@ static const struct file_operations sclp_ctl_fops = {
.owner = THIS_MODULE,
.open = nonseekable_open,
.unlocked_ioctl = sclp_ctl_ioctl,
- .compat_ioctl = sclp_ctl_ioctl,
};
/*
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c
index bd5e5ba50c0a..6bf501ad8ff0 100644
--- a/drivers/s390/char/sclp_early.c
+++ b/drivers/s390/char/sclp_early.c
@@ -5,8 +5,7 @@
* Copyright IBM Corp. 2013
*/
-#define KMSG_COMPONENT "sclp_early"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "sclp_early: " fmt
#include <linux/export.h>
#include <linux/errno.h>
diff --git a/drivers/s390/char/sclp_ftp.c b/drivers/s390/char/sclp_ftp.c
index d27e2cbfbccb..2a1c4b2cafc8 100644
--- a/drivers/s390/char/sclp_ftp.c
+++ b/drivers/s390/char/sclp_ftp.c
@@ -7,8 +7,7 @@
*
*/
-#define KMSG_COMPONENT "hmcdrv"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "hmcdrv: " fmt
#include <linux/kernel.h>
#include <linux/mm.h>
diff --git a/drivers/s390/char/sclp_mem.c b/drivers/s390/char/sclp_mem.c
index 27f49f5fd358..676c085b4f8a 100644
--- a/drivers/s390/char/sclp_mem.c
+++ b/drivers/s390/char/sclp_mem.c
@@ -5,13 +5,15 @@
* Copyright IBM Corp. 2025
*/
-#define KMSG_COMPONENT "sclp_mem"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "sclp_mem: " fmt
#include <linux/cpufeature.h>
+#include <linux/container_of.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/kstrtox.h>
#include <linux/memory.h>
#include <linux/memory_hotplug.h>
#include <linux/mm.h>
@@ -27,7 +29,6 @@
#define SCLP_CMDW_ASSIGN_STORAGE 0x000d0001
#define SCLP_CMDW_UNASSIGN_STORAGE 0x000c0001
-static DEFINE_MUTEX(sclp_mem_mutex);
static LIST_HEAD(sclp_mem_list);
static u8 sclp_max_storage_id;
static DECLARE_BITMAP(sclp_storage_ids, 256);
@@ -38,6 +39,18 @@ struct memory_increment {
int standby;
};
+struct sclp_mem {
+ struct kobject kobj;
+ unsigned int id;
+ unsigned int memmap_on_memory;
+ unsigned int config;
+};
+
+struct sclp_mem_arg {
+ struct sclp_mem *sclp_mems;
+ struct kset *kset;
+};
+
struct assign_storage_sccb {
struct sccb_header header;
u16 rn;
@@ -163,92 +176,168 @@ static int sclp_mem_change_state(unsigned long start, unsigned long size,
return rc ? -EIO : 0;
}
-static bool contains_standby_increment(unsigned long start, unsigned long end)
+static ssize_t sclp_config_mem_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
- struct memory_increment *incr;
- unsigned long istart;
+ struct sclp_mem *sclp_mem = container_of(kobj, struct sclp_mem, kobj);
- list_for_each_entry(incr, &sclp_mem_list, list) {
- istart = rn2addr(incr->rn);
- if (end - 1 < istart)
- continue;
- if (start > istart + sclp.rzm - 1)
- continue;
- if (incr->standby)
- return true;
- }
- return false;
+ return sysfs_emit(buf, "%u\n", READ_ONCE(sclp_mem->config));
}
-static int sclp_mem_notifier(struct notifier_block *nb,
- unsigned long action, void *data)
+static ssize_t sclp_config_mem_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
{
- unsigned long start, size;
- struct memory_notify *arg;
+ unsigned long addr, block_size;
+ struct sclp_mem *sclp_mem;
+ struct memory_block *mem;
unsigned char id;
- int rc = 0;
+ bool value;
+ int rc;
- arg = data;
- start = arg->start_pfn << PAGE_SHIFT;
- size = arg->nr_pages << PAGE_SHIFT;
- mutex_lock(&sclp_mem_mutex);
+ rc = kstrtobool(buf, &value);
+ if (rc)
+ return rc;
+ sclp_mem = container_of(kobj, struct sclp_mem, kobj);
+ block_size = memory_block_size_bytes();
+ addr = sclp_mem->id * block_size;
+ /*
+ * Hold device_hotplug_lock when adding/removing memory blocks.
+ * Additionally, also protect calls to find_memory_block() and
+ * sclp_attach_storage().
+ */
+ rc = lock_device_hotplug_sysfs();
+ if (rc)
+ goto out;
for_each_clear_bit(id, sclp_storage_ids, sclp_max_storage_id + 1)
sclp_attach_storage(id);
- switch (action) {
- case MEM_GOING_OFFLINE:
- /*
- * Do not allow to set memory blocks offline that contain
- * standby memory. This is done to simplify the "memory online"
- * case.
- */
- if (contains_standby_increment(start, start + size))
- rc = -EPERM;
- break;
- case MEM_PREPARE_ONLINE:
+ if (value) {
+ if (sclp_mem->config)
+ goto out_unlock;
+ rc = sclp_mem_change_state(addr, block_size, 1);
+ if (rc)
+ goto out_unlock;
/*
- * Access the altmap_start_pfn and altmap_nr_pages fields
- * within the struct memory_notify specifically when dealing
- * with only MEM_PREPARE_ONLINE/MEM_FINISH_OFFLINE notifiers.
- *
- * When altmap is in use, take the specified memory range
- * online, which includes the altmap.
+ * Set entire memory block CMMA state to nodat. Later, when
+ * page tables pages are allocated via __add_memory(), those
+ * regions are marked __arch_set_page_dat().
*/
- if (arg->altmap_nr_pages) {
- start = PFN_PHYS(arg->altmap_start_pfn);
- size += PFN_PHYS(arg->altmap_nr_pages);
+ __arch_set_page_nodat((void *)__va(addr), block_size >> PAGE_SHIFT);
+ rc = __add_memory(0, addr, block_size,
+ sclp_mem->memmap_on_memory ?
+ MHP_MEMMAP_ON_MEMORY : MHP_NONE);
+ if (rc) {
+ sclp_mem_change_state(addr, block_size, 0);
+ goto out_unlock;
}
- rc = sclp_mem_change_state(start, size, 1);
- if (rc || !arg->altmap_nr_pages)
- break;
- /*
- * Set CMMA state to nodat here, since the struct page memory
- * at the beginning of the memory block will not go through the
- * buddy allocator later.
- */
- __arch_set_page_nodat((void *)__va(start), arg->altmap_nr_pages);
- break;
- case MEM_FINISH_OFFLINE:
- /*
- * When altmap is in use, take the specified memory range
- * offline, which includes the altmap.
- */
- if (arg->altmap_nr_pages) {
- start = PFN_PHYS(arg->altmap_start_pfn);
- size += PFN_PHYS(arg->altmap_nr_pages);
+ mem = find_memory_block(pfn_to_section_nr(PFN_DOWN(addr)));
+ put_device(&mem->dev);
+ WRITE_ONCE(sclp_mem->config, 1);
+ } else {
+ if (!sclp_mem->config)
+ goto out_unlock;
+ mem = find_memory_block(pfn_to_section_nr(PFN_DOWN(addr)));
+ if (mem->state != MEM_OFFLINE) {
+ put_device(&mem->dev);
+ rc = -EBUSY;
+ goto out_unlock;
}
- sclp_mem_change_state(start, size, 0);
- break;
- default:
- break;
+ /* drop the ref just got via find_memory_block() */
+ put_device(&mem->dev);
+ sclp_mem_change_state(addr, block_size, 0);
+ __remove_memory(addr, block_size);
+ WRITE_ONCE(sclp_mem->config, 0);
+ }
+out_unlock:
+ unlock_device_hotplug();
+out:
+ return rc ? rc : count;
+}
+
+static struct kobj_attribute sclp_config_mem_attr =
+ __ATTR(config, 0644, sclp_config_mem_show, sclp_config_mem_store);
+
+static ssize_t sclp_memmap_on_memory_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ struct sclp_mem *sclp_mem = container_of(kobj, struct sclp_mem, kobj);
+
+ return sysfs_emit(buf, "%u\n", READ_ONCE(sclp_mem->memmap_on_memory));
+}
+
+static ssize_t sclp_memmap_on_memory_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sclp_mem *sclp_mem;
+ unsigned long block_size;
+ struct memory_block *mem;
+ bool value;
+ int rc;
+
+ rc = kstrtobool(buf, &value);
+ if (rc)
+ return rc;
+ if (value && !mhp_supports_memmap_on_memory())
+ return -EOPNOTSUPP;
+ rc = lock_device_hotplug_sysfs();
+ if (rc)
+ return rc;
+ block_size = memory_block_size_bytes();
+ sclp_mem = container_of(kobj, struct sclp_mem, kobj);
+ mem = find_memory_block(pfn_to_section_nr(PFN_DOWN(sclp_mem->id * block_size)));
+ if (!mem) {
+ WRITE_ONCE(sclp_mem->memmap_on_memory, value);
+ } else {
+ put_device(&mem->dev);
+ rc = -EBUSY;
}
- mutex_unlock(&sclp_mem_mutex);
- return rc ? NOTIFY_BAD : NOTIFY_OK;
+ unlock_device_hotplug();
+ return rc ? rc : count;
}
-static struct notifier_block sclp_mem_nb = {
- .notifier_call = sclp_mem_notifier,
+static const struct kobj_type ktype = {
+ .sysfs_ops = &kobj_sysfs_ops,
+};
+
+static struct kobj_attribute sclp_memmap_attr =
+ __ATTR(memmap_on_memory, 0644, sclp_memmap_on_memory_show, sclp_memmap_on_memory_store);
+
+static struct attribute *sclp_mem_attrs[] = {
+ &sclp_config_mem_attr.attr,
+ &sclp_memmap_attr.attr,
+ NULL,
};
+static struct attribute_group sclp_mem_attr_group = {
+ .attrs = sclp_mem_attrs,
+};
+
+static int sclp_create_mem(struct sclp_mem *sclp_mem, struct kset *kset,
+ unsigned int id, bool config, bool memmap_on_memory)
+{
+ int rc;
+
+ sclp_mem->memmap_on_memory = memmap_on_memory;
+ sclp_mem->config = config;
+ sclp_mem->id = id;
+ kobject_init(&sclp_mem->kobj, &ktype);
+ rc = kobject_add(&sclp_mem->kobj, &kset->kobj, "memory%d", id);
+ if (rc)
+ return rc;
+ return sysfs_create_group(&sclp_mem->kobj, &sclp_mem_attr_group);
+}
+
+static int sclp_create_configured_mem(struct memory_block *mem, void *argument)
+{
+ struct sclp_mem *sclp_mems;
+ struct sclp_mem_arg *arg;
+ struct kset *kset;
+ unsigned int id;
+
+ id = mem->dev.id;
+ arg = (struct sclp_mem_arg *)argument;
+ sclp_mems = arg->sclp_mems;
+ kset = arg->kset;
+ return sclp_create_mem(&sclp_mems[id], kset, id, true, false);
+}
+
static void __init align_to_block_size(unsigned long *start,
unsigned long *size,
unsigned long alignment)
@@ -264,14 +353,17 @@ static void __init align_to_block_size(unsigned long *start,
*size = size_align;
}
-static void __init add_memory_merged(u16 rn)
+static int __init sclp_create_standby_mems_merged(struct sclp_mem *sclp_mems,
+ struct kset *kset, u16 rn)
{
unsigned long start, size, addr, block_size;
static u16 first_rn, num;
+ unsigned int id;
+ int rc = 0;
if (rn && first_rn && (first_rn + num == rn)) {
num++;
- return;
+ return rc;
}
if (!first_rn)
goto skip_add;
@@ -286,24 +378,57 @@ static void __init add_memory_merged(u16 rn)
if (!size)
goto skip_add;
for (addr = start; addr < start + size; addr += block_size) {
- add_memory(0, addr, block_size,
- cpu_has_edat1() ?
- MHP_MEMMAP_ON_MEMORY | MHP_OFFLINE_INACCESSIBLE : MHP_NONE);
+ id = addr / block_size;
+ rc = sclp_create_mem(&sclp_mems[id], kset, id, false,
+ mhp_supports_memmap_on_memory());
+ if (rc)
+ break;
}
skip_add:
first_rn = rn;
num = 1;
+ return rc;
}
-static void __init sclp_add_standby_memory(void)
+static int __init sclp_create_standby_mems(struct sclp_mem *sclp_mems, struct kset *kset)
{
struct memory_increment *incr;
+ int rc = 0;
list_for_each_entry(incr, &sclp_mem_list, list) {
if (incr->standby)
- add_memory_merged(incr->rn);
+ rc = sclp_create_standby_mems_merged(sclp_mems, kset, incr->rn);
+ if (rc)
+ return rc;
}
- add_memory_merged(0);
+ return sclp_create_standby_mems_merged(sclp_mems, kset, 0);
+}
+
+static int __init sclp_init_mem(void)
+{
+ const unsigned long block_size = memory_block_size_bytes();
+ unsigned int max_sclp_mems;
+ struct sclp_mem *sclp_mems;
+ struct sclp_mem_arg arg;
+ struct kset *kset;
+ int rc;
+
+ max_sclp_mems = roundup(sclp.rnmax * sclp.rzm, block_size) / block_size;
+ /* Allocate memory for all blocks ahead of time. */
+ sclp_mems = kcalloc(max_sclp_mems, sizeof(struct sclp_mem), GFP_KERNEL);
+ if (!sclp_mems)
+ return -ENOMEM;
+ kset = kset_create_and_add("memory", NULL, firmware_kobj);
+ if (!kset)
+ return -ENOMEM;
+ /* Initial memory is in the "configured" state already. */
+ arg.sclp_mems = sclp_mems;
+ arg.kset = kset;
+ rc = for_each_memory_block(&arg, sclp_create_configured_mem);
+ if (rc)
+ return rc;
+ /* Standby memory is "deconfigured". */
+ return sclp_create_standby_mems(sclp_mems, kset);
}
static void __init insert_increment(u16 rn, int standby, int assigned)
@@ -336,7 +461,7 @@ static void __init insert_increment(u16 rn, int standby, int assigned)
list_add(&new_incr->list, prev);
}
-static int __init sclp_detect_standby_memory(void)
+static int __init sclp_setup_memory(void)
{
struct read_storage_sccb *sccb;
int i, id, assigned, rc;
@@ -388,12 +513,9 @@ static int __init sclp_detect_standby_memory(void)
goto out;
for (i = 1; i <= sclp.rnmax - assigned; i++)
insert_increment(0, 1, 0);
- rc = register_memory_notifier(&sclp_mem_nb);
- if (rc)
- goto out;
- sclp_add_standby_memory();
+ rc = sclp_init_mem();
out:
free_page((unsigned long)sccb);
return rc;
}
-__initcall(sclp_detect_standby_memory);
+__initcall(sclp_setup_memory);
diff --git a/drivers/s390/char/sclp_ocf.c b/drivers/s390/char/sclp_ocf.c
index ae2479b804d8..35f3a4a08b12 100644
--- a/drivers/s390/char/sclp_ocf.c
+++ b/drivers/s390/char/sclp_ocf.c
@@ -6,8 +6,7 @@
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#define KMSG_COMPONENT "sclp_ocf"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "sclp_ocf: " fmt
#include <linux/export.h>
#include <linux/kernel.h>
diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c
index 56400886f7fc..899063e64aef 100644
--- a/drivers/s390/char/sclp_pci.c
+++ b/drivers/s390/char/sclp_pci.c
@@ -4,8 +4,7 @@
*
* Copyright IBM Corp. 2016
*/
-#define KMSG_COMPONENT "sclp_cmd"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "sclp_cmd: " fmt
#include <linux/completion.h>
#include <linux/export.h>
diff --git a/drivers/s390/char/sclp_sd.c b/drivers/s390/char/sclp_sd.c
index 129b89fe40a3..bb1bce70ec00 100644
--- a/drivers/s390/char/sclp_sd.c
+++ b/drivers/s390/char/sclp_sd.c
@@ -5,8 +5,7 @@
* Copyright IBM Corp. 2017
*/
-#define KMSG_COMPONENT "sclp_sd"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "sclp_sd: " fmt
#include <linux/completion.h>
#include <linux/jiffies.h>
diff --git a/drivers/s390/char/sclp_sdias.c b/drivers/s390/char/sclp_sdias.c
index e915a343fcf5..ab8f1b758a1a 100644
--- a/drivers/s390/char/sclp_sdias.c
+++ b/drivers/s390/char/sclp_sdias.c
@@ -6,8 +6,7 @@
* Author(s): Michael Holzheu
*/
-#define KMSG_COMPONENT "sclp_sdias"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "sclp_sdias: " fmt
#include <linux/completion.h>
#include <linux/sched.h>
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index 0aba30efb483..3953b31b0c55 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -130,6 +130,7 @@ struct tape_request {
int retries; /* retry counter for error recovery. */
int rescnt; /* residual count from devstat. */
struct timer_list timer; /* timer for std_assign_timeout(). */
+ struct irb irb; /* device status */
/* Callback for delivering final status. */
void (*callback)(struct tape_request *, void *);
@@ -151,8 +152,8 @@ struct tape_discipline {
int (*setup_device)(struct tape_device *);
void (*cleanup_device)(struct tape_device *);
int (*irq)(struct tape_device *, struct tape_request *, struct irb *);
- struct tape_request *(*read_block)(struct tape_device *, size_t);
- struct tape_request *(*write_block)(struct tape_device *, size_t);
+ struct tape_request *(*read_block)(struct tape_device *);
+ struct tape_request *(*write_block)(struct tape_device *);
void (*process_eov)(struct tape_device*);
/* ioctl function for additional ioctls. */
int (*ioctl_fn)(struct tape_device *, unsigned int, unsigned long);
@@ -172,7 +173,7 @@ struct tape_discipline {
/* Char Frontend Data */
struct tape_char_data {
- struct idal_buffer *idal_buf; /* idal buffer for user char data */
+ struct idal_buffer **ibs; /* idal buffer array for user char data */
int block_size; /* of size block_size. */
};
@@ -234,6 +235,7 @@ struct tape_device {
/* Externals from tape_core.c */
extern struct tape_request *tape_alloc_request(int cplength, int datasize);
extern void tape_free_request(struct tape_request *);
+extern int tape_check_idalbuffer(struct tape_device *device, size_t size);
extern int tape_do_io(struct tape_device *, struct tape_request *);
extern int tape_do_io_async(struct tape_device *, struct tape_request *);
extern int tape_do_io_interruptible(struct tape_device *, struct tape_request *);
@@ -347,12 +349,21 @@ tape_ccw_repeat(struct ccw1 *ccw, __u8 cmd_code, int count)
}
static inline struct ccw1 *
+tape_ccw_dc_idal(struct ccw1 *ccw, __u8 cmd_code, struct idal_buffer *idal)
+{
+ ccw->cmd_code = cmd_code;
+ ccw->flags = CCW_FLAG_DC;
+ idal_buffer_set_cda(idal, ccw);
+ return ccw + 1;
+}
+
+static inline struct ccw1 *
tape_ccw_cc_idal(struct ccw1 *ccw, __u8 cmd_code, struct idal_buffer *idal)
{
ccw->cmd_code = cmd_code;
ccw->flags = CCW_FLAG_CC;
idal_buffer_set_cda(idal, ccw);
- return ccw++;
+ return ccw + 1;
}
static inline struct ccw1 *
@@ -361,7 +372,7 @@ tape_ccw_end_idal(struct ccw1 *ccw, __u8 cmd_code, struct idal_buffer *idal)
ccw->cmd_code = cmd_code;
ccw->flags = 0;
idal_buffer_set_cda(idal, ccw);
- return ccw++;
+ return ccw + 1;
}
/* Global vars */
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 1e4984acb648..a13e0ac1a4e2 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -8,8 +8,7 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#define KMSG_COMPONENT "tape_34xx"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "tape_34xx: " fmt
#include <linux/export.h>
#include <linux/module.h>
@@ -234,31 +233,6 @@ tape_34xx_unsolicited_irq(struct tape_device *device, struct irb *irb)
return TAPE_IO_SUCCESS;
}
-/*
- * Read Opposite Error Recovery Function:
- * Used, when Read Forward does not work
- */
-static int
-tape_34xx_erp_read_opposite(struct tape_device *device,
- struct tape_request *request)
-{
- if (request->op == TO_RFO) {
- /*
- * We did read forward, but the data could not be read
- * *correctly*. We transform the request to a read backward
- * and try again.
- */
- tape_std_read_backward(device, request);
- return tape_34xx_erp_retry(request);
- }
-
- /*
- * We tried to read forward and backward, but hat no
- * success -> failed.
- */
- return tape_34xx_erp_failed(request, -EIO);
-}
-
static int
tape_34xx_erp_bug(struct tape_device *device, struct tape_request *request,
struct irb *irb, int no)
@@ -440,9 +414,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
dev_warn (&device->cdev->dev, "A write error on the "
"tape cannot be recovered\n");
return tape_34xx_erp_failed(request, -EIO);
- case 0x26:
- /* Data Check (read opposite) occurred. */
- return tape_34xx_erp_read_opposite(device, request);
case 0x28:
/* ID-Mark at tape start couldn't be written */
dev_warn (&device->cdev->dev, "Writing the ID-mark "
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 2a2931d303cb..0d80f43b175d 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -8,8 +8,7 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#define KMSG_COMPONENT "tape_3590"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "tape_3590: " fmt
#include <linux/export.h>
#include <linux/module.h>
@@ -551,31 +550,6 @@ tape_3590_mtseek(struct tape_device *device, int count)
}
/*
- * Read Opposite Error Recovery Function:
- * Used, when Read Forward does not work
- */
-static void
-tape_3590_read_opposite(struct tape_device *device,
- struct tape_request *request)
-{
- struct tape_3590_disc_data *data;
-
- /*
- * We have allocated 4 ccws in tape_std_read, so we can now
- * transform the request to a read backward, followed by a
- * forward space block.
- */
- request->op = TO_RBA;
- tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
- data = device->discdata;
- tape_ccw_cc_idal(request->cpaddr + 1, data->read_back_op,
- device->char_data.idal_buf);
- tape_ccw_cc(request->cpaddr + 2, FORSPACEBLOCK, 0, NULL);
- tape_ccw_end(request->cpaddr + 3, NOP, 0, NULL);
- DBF_EVENT(6, "xrop ccwg\n");
-}
-
-/*
* Read Attention Msg
* This should be done after an interrupt with attention bit (0x80)
* in device state.
@@ -897,60 +871,6 @@ tape_3590_erp_special_interrupt(struct tape_device *device,
}
/*
- * RDA: Read Alternate
- */
-static int
-tape_3590_erp_read_alternate(struct tape_device *device,
- struct tape_request *request, struct irb *irb)
-{
- struct tape_3590_disc_data *data;
-
- /*
- * The issued Read Backward or Read Previous command is not
- * supported by the device
- * The recovery action should be to issue another command:
- * Read Revious: if Read Backward is not supported
- * Read Backward: if Read Previous is not supported
- */
- data = device->discdata;
- if (data->read_back_op == READ_PREVIOUS) {
- DBF_EVENT(2, "(%08x): No support for READ_PREVIOUS command\n",
- device->cdev_id);
- data->read_back_op = READ_BACKWARD;
- } else {
- DBF_EVENT(2, "(%08x): No support for READ_BACKWARD command\n",
- device->cdev_id);
- data->read_back_op = READ_PREVIOUS;
- }
- tape_3590_read_opposite(device, request);
- return tape_3590_erp_retry(device, request, irb);
-}
-
-/*
- * Error Recovery read opposite
- */
-static int
-tape_3590_erp_read_opposite(struct tape_device *device,
- struct tape_request *request, struct irb *irb)
-{
- switch (request->op) {
- case TO_RFO:
- /*
- * We did read forward, but the data could not be read.
- * We will read backward and then skip forward again.
- */
- tape_3590_read_opposite(device, request);
- return tape_3590_erp_retry(device, request, irb);
- case TO_RBA:
- /* We tried to read forward and backward, but hat no success */
- return tape_3590_erp_failed(device, request, irb, -EIO);
- break;
- default:
- return tape_3590_erp_failed(device, request, irb, -EIO);
- }
-}
-
-/*
* Print an MIM (Media Information Message) (message code f0)
*/
static void
@@ -1348,10 +1268,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
tape_3590_print_era_msg(device, irb);
return tape_3590_erp_read_buf_log(device, request, irb);
- case 0x2011:
- tape_3590_print_era_msg(device, irb);
- return tape_3590_erp_read_alternate(device, request, irb);
-
case 0x2230:
case 0x2231:
tape_3590_print_era_msg(device, irb);
@@ -1405,12 +1321,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
tape_3590_print_era_msg(device, irb);
return tape_3590_erp_swap(device, request, irb);
}
- if (sense->rac == 0x26) {
- /* Read Opposite */
- tape_3590_print_era_msg(device, irb);
- return tape_3590_erp_read_opposite(device, request,
- irb);
- }
return tape_3590_erp_basic(device, request, irb, -EIO);
case 0x5020:
case 0x5021:
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 89778d922d9f..c5d3c303c15c 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -10,14 +10,12 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#define KMSG_COMPONENT "tape"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "tape: " fmt
#include <linux/module.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/mtio.h>
-#include <linux/compat.h>
#include <linux/uaccess.h>
@@ -37,9 +35,6 @@ static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t
static int tapechar_open(struct inode *,struct file *);
static int tapechar_release(struct inode *,struct file *);
static long tapechar_ioctl(struct file *, unsigned int, unsigned long);
-#ifdef CONFIG_COMPAT
-static long tapechar_compat_ioctl(struct file *, unsigned int, unsigned long);
-#endif
static const struct file_operations tape_fops =
{
@@ -47,9 +42,6 @@ static const struct file_operations tape_fops =
.read = tapechar_read,
.write = tapechar_write,
.unlocked_ioctl = tapechar_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = tapechar_compat_ioctl,
-#endif
.open = tapechar_open,
.release = tapechar_release,
};
@@ -64,7 +56,7 @@ tapechar_setup_device(struct tape_device * device)
{
char device_name[20];
- sprintf(device_name, "ntibm%i", device->first_minor / 2);
+ scnprintf(device_name, sizeof(device_name), "ntibm%i", device->first_minor / 2);
device->nt = register_tape_dev(
&device->cdev->dev,
MKDEV(tapechar_major, device->first_minor),
@@ -93,33 +85,6 @@ tapechar_cleanup_device(struct tape_device *device)
device->nt = NULL;
}
-static int
-tapechar_check_idalbuffer(struct tape_device *device, size_t block_size)
-{
- struct idal_buffer *new;
-
- if (device->char_data.idal_buf != NULL &&
- device->char_data.idal_buf->size == block_size)
- return 0;
-
- if (block_size > MAX_BLOCKSIZE) {
- DBF_EVENT(3, "Invalid blocksize (%zd > %d)\n",
- block_size, MAX_BLOCKSIZE);
- return -EINVAL;
- }
-
- /* The current idal buffer is not correct. Allocate a new one. */
- new = idal_buffer_alloc(block_size, 0);
- if (IS_ERR(new))
- return -ENOMEM;
-
- if (device->char_data.idal_buf != NULL)
- idal_buffer_free(device->char_data.idal_buf);
-
- device->char_data.idal_buf = new;
-
- return 0;
-}
/*
* Tape device read function
@@ -127,9 +92,12 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size)
static ssize_t
tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
{
- struct tape_device *device;
struct tape_request *request;
+ struct ccw1 *ccw, *last_ccw;
+ struct tape_device *device;
+ struct idal_buffer **ibs;
size_t block_size;
+ size_t read = 0;
int rc;
DBF_EVENT(6, "TCHAR:read\n");
@@ -156,24 +124,37 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
block_size = count;
}
- rc = tapechar_check_idalbuffer(device, block_size);
+ rc = tape_check_idalbuffer(device, block_size);
if (rc)
return rc;
DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size);
/* Let the discipline build the ccw chain. */
- request = device->discipline->read_block(device, block_size);
+ request = device->discipline->read_block(device);
if (IS_ERR(request))
return PTR_ERR(request);
/* Execute it. */
rc = tape_do_io(device, request);
if (rc == 0) {
- rc = block_size - request->rescnt;
DBF_EVENT(6, "TCHAR:rbytes: %x\n", rc);
- /* Copy data from idal buffer to user space. */
- if (idal_buffer_to_user(device->char_data.idal_buf,
- data, rc) != 0)
- rc = -EFAULT;
+ /* Channel Program Address (cpa) points to last CCW + 8 */
+ last_ccw = dma32_to_virt(request->irb.scsw.cmd.cpa);
+ ccw = request->cpaddr;
+ ibs = device->char_data.ibs;
+ while (++ccw < last_ccw) {
+ /* Copy data from idal buffer to user space. */
+ if (idal_buffer_to_user(*ibs++, data, ccw->count) != 0) {
+ rc = -EFAULT;
+ break;
+ }
+ read += ccw->count;
+ data += ccw->count;
+ }
+ if (&last_ccw[-1] == &request->cpaddr[1] &&
+ request->rescnt == last_ccw[-1].count)
+ rc = 0;
+ else
+ rc = read - request->rescnt;
}
tape_free_request(request);
return rc;
@@ -185,10 +166,12 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
static ssize_t
tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t *ppos)
{
- struct tape_device *device;
struct tape_request *request;
+ struct ccw1 *ccw, *last_ccw;
+ struct tape_device *device;
+ struct idal_buffer **ibs;
+ size_t written = 0;
size_t block_size;
- size_t written;
int nblocks;
int i, rc;
@@ -208,35 +191,45 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t
nblocks = 1;
}
- rc = tapechar_check_idalbuffer(device, block_size);
+ rc = tape_check_idalbuffer(device, block_size);
if (rc)
return rc;
- DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size);
+ DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size);
DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks);
/* Let the discipline build the ccw chain. */
- request = device->discipline->write_block(device, block_size);
+ request = device->discipline->write_block(device);
if (IS_ERR(request))
return PTR_ERR(request);
- rc = 0;
- written = 0;
+
for (i = 0; i < nblocks; i++) {
- /* Copy data from user space to idal buffer. */
- if (idal_buffer_from_user(device->char_data.idal_buf,
- data, block_size)) {
- rc = -EFAULT;
- break;
+ size_t wbytes = 0; /* Used to trace written data in dbf */
+
+ ibs = device->char_data.ibs;
+ while (ibs && *ibs) {
+ if (idal_buffer_from_user(*ibs, data, (*ibs)->size)) {
+ rc = -EFAULT;
+ goto out;
+ }
+ data += (*ibs)->size;
+ ibs++;
}
rc = tape_do_io(device, request);
if (rc)
- break;
- DBF_EVENT(6, "TCHAR:wbytes: %lx\n",
- block_size - request->rescnt);
- written += block_size - request->rescnt;
+ goto out;
+
+ /* Channel Program Address (cpa) points to last CCW + 8 */
+ last_ccw = dma32_to_virt(request->irb.scsw.cmd.cpa);
+ ccw = request->cpaddr;
+ while (++ccw < last_ccw)
+ wbytes += ccw->count;
+ DBF_EVENT(6, "TCHAR:wbytes: %lx\n", wbytes - request->rescnt);
+ written += wbytes - request->rescnt;
if (request->rescnt != 0)
break;
- data += block_size;
}
+
+out:
tape_free_request(request);
if (rc == -ENOSPC) {
/*
@@ -324,10 +317,8 @@ tapechar_release(struct inode *inode, struct file *filp)
}
}
- if (device->char_data.idal_buf != NULL) {
- idal_buffer_free(device->char_data.idal_buf);
- device->char_data.idal_buf = NULL;
- }
+ if (device->char_data.ibs)
+ idal_buffer_array_free(&device->char_data.ibs);
tape_release(device);
filp->private_data = NULL;
tape_put_device(device);
@@ -442,25 +433,6 @@ tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data)
return rc;
}
-#ifdef CONFIG_COMPAT
-static long
-tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
-{
- struct tape_device *device = filp->private_data;
- long rc;
-
- if (no == MTIOCPOS32)
- no = MTIOCPOS;
- else if (no == MTIOCGET32)
- no = MTIOCGET;
-
- mutex_lock(&device->mutex);
- rc = __tapechar_ioctl(device, no, compat_ptr(data));
- mutex_unlock(&device->mutex);
- return rc;
-}
-#endif /* CONFIG_COMPAT */
-
/*
* Initialize character device frontend.
*/
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index fb18adfb95b5..6fa7b7824856 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -8,8 +8,7 @@
* Based on simple class device code by Greg K-H
*/
-#define KMSG_COMPONENT "tape"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "tape: " fmt
#include <linux/export.h>
#include <linux/slab.h>
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 6ec812280221..0250076a7d9f 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -11,8 +11,7 @@
* Stefan Bader <shbader@de.ibm.com>
*/
-#define KMSG_COMPONENT "tape"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "tape: " fmt
#include <linux/export.h>
#include <linux/module.h>
@@ -726,6 +725,36 @@ tape_free_request (struct tape_request * request)
kfree(request);
}
+int
+tape_check_idalbuffer(struct tape_device *device, size_t size)
+{
+ struct idal_buffer **new;
+ size_t old_size = 0;
+
+ old_size = idal_buffer_array_datasize(device->char_data.ibs);
+ if (old_size == size)
+ return 0;
+
+ if (size > MAX_BLOCKSIZE) {
+ DBF_EVENT(3, "Invalid blocksize (%zd > %d)\n",
+ size, MAX_BLOCKSIZE);
+ return -EINVAL;
+ }
+
+ /* The current idal buffer is not correct. Allocate a new one. */
+ new = idal_buffer_array_alloc(size, 0);
+ if (IS_ERR(new))
+ return -ENOMEM;
+
+ /* Free old idal buffer array */
+ if (device->char_data.ibs)
+ idal_buffer_array_free(&device->char_data.ibs);
+
+ device->char_data.ibs = new;
+
+ return 0;
+}
+
static int
__tape_start_io(struct tape_device *device, struct tape_request *request)
{
@@ -1099,9 +1128,10 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
}
/* May be an unsolicited irq */
- if(request != NULL)
+ if (request != NULL) {
request->rescnt = irb->scsw.cmd.count;
- else if ((irb->scsw.cmd.dstat == 0x85 || irb->scsw.cmd.dstat == 0x80) &&
+ memcpy(&request->irb, irb, sizeof(*irb));
+ } else if ((irb->scsw.cmd.dstat == 0x85 || irb->scsw.cmd.dstat == 0x80) &&
!list_empty(&device->req_queue)) {
/* Not Ready to Ready after long busy ? */
struct tape_request *req;
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index 2238d9df6c47..a1e5fab12af2 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -11,8 +11,7 @@
* PROCFS Functions
*/
-#define KMSG_COMPONENT "tape"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "tape: " fmt
#include <linux/module.h>
#include <linux/vmalloc.h>
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c
index 176ae8e2eb6b..43a5586685ff 100644
--- a/drivers/s390/char/tape_std.c
+++ b/drivers/s390/char/tape_std.c
@@ -11,8 +11,7 @@
* Stefan Bader <shbader@de.ibm.com>
*/
-#define KMSG_COMPONENT "tape"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "tape: " fmt
#include <linux/export.h>
#include <linux/stddef.h>
@@ -212,7 +211,7 @@ tape_std_mtload(struct tape_device *device, int count)
int
tape_std_mtsetblk(struct tape_device *device, int count)
{
- struct idal_buffer *new;
+ int rc;
DBF_LH(6, "tape_std_mtsetblk(%d)\n", count);
if (count <= 0) {
@@ -224,26 +223,12 @@ tape_std_mtsetblk(struct tape_device *device, int count)
device->char_data.block_size = 0;
return 0;
}
- if (device->char_data.idal_buf != NULL &&
- device->char_data.idal_buf->size == count)
- /* We already have a idal buffer of that size. */
- return 0;
- if (count > MAX_BLOCKSIZE) {
- DBF_EVENT(3, "Invalid block size (%d > %d) given.\n",
- count, MAX_BLOCKSIZE);
- return -EINVAL;
- }
+ rc = tape_check_idalbuffer(device, count);
+ if (rc)
+ return rc;
- /* Allocate a new idal buffer. */
- new = idal_buffer_alloc(count, 0);
- if (IS_ERR(new))
- return -ENOMEM;
- if (device->char_data.idal_buf != NULL)
- idal_buffer_free(device->char_data.idal_buf);
- device->char_data.idal_buf = new;
device->char_data.block_size = count;
-
DBF_LH(6, "new blocksize is %d\n", device->char_data.block_size);
return 0;
@@ -641,63 +626,54 @@ tape_std_mtcompression(struct tape_device *device, int mt_count)
* Read Block
*/
struct tape_request *
-tape_std_read_block(struct tape_device *device, size_t count)
+tape_std_read_block(struct tape_device *device)
{
struct tape_request *request;
+ struct idal_buffer **ibs;
+ struct ccw1 *ccw;
+ size_t count;
- /*
- * We have to alloc 4 ccws in order to be able to transform request
- * into a read backward request in error case.
- */
- request = tape_alloc_request(4, 0);
+ ibs = device->char_data.ibs;
+ count = idal_buffer_array_size(ibs);
+ request = tape_alloc_request(count + 1 /* MODE_SET_DB */, 0);
if (IS_ERR(request)) {
DBF_EXCEPTION(6, "xrbl fail");
return request;
}
request->op = TO_RFO;
- tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
- tape_ccw_end_idal(request->cpaddr + 1, READ_FORWARD,
- device->char_data.idal_buf);
+ ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
+ while (count-- > 1)
+ ccw = tape_ccw_dc_idal(ccw, READ_FORWARD, *ibs++);
+ tape_ccw_end_idal(ccw, READ_FORWARD, *ibs);
+
DBF_EVENT(6, "xrbl ccwg\n");
return request;
}
/*
- * Read Block backward transformation function.
- */
-void
-tape_std_read_backward(struct tape_device *device, struct tape_request *request)
-{
- /*
- * We have allocated 4 ccws in tape_std_read, so we can now
- * transform the request to a read backward, followed by a
- * forward space block.
- */
- request->op = TO_RBA;
- tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
- tape_ccw_cc_idal(request->cpaddr + 1, READ_BACKWARD,
- device->char_data.idal_buf);
- tape_ccw_cc(request->cpaddr + 2, FORSPACEBLOCK, 0, NULL);
- tape_ccw_end(request->cpaddr + 3, NOP, 0, NULL);
- DBF_EVENT(6, "xrop ccwg");}
-
-/*
* Write Block
*/
struct tape_request *
-tape_std_write_block(struct tape_device *device, size_t count)
+tape_std_write_block(struct tape_device *device)
{
struct tape_request *request;
+ struct idal_buffer **ibs;
+ struct ccw1 *ccw;
+ size_t count;
- request = tape_alloc_request(2, 0);
+ count = idal_buffer_array_size(device->char_data.ibs);
+ request = tape_alloc_request(count + 1 /* MODE_SET_DB */, 0);
if (IS_ERR(request)) {
DBF_EXCEPTION(6, "xwbl fail\n");
return request;
}
request->op = TO_WRI;
- tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
- tape_ccw_end_idal(request->cpaddr + 1, WRITE_CMD,
- device->char_data.idal_buf);
+ ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
+ ibs = device->char_data.ibs;
+ while (count-- > 1)
+ ccw = tape_ccw_dc_idal(ccw, WRITE_CMD, *ibs++);
+ tape_ccw_end_idal(ccw, WRITE_CMD, *ibs);
+
DBF_EVENT(6, "xwbl ccwg\n");
return request;
}
@@ -741,6 +717,5 @@ EXPORT_SYMBOL(tape_std_mterase);
EXPORT_SYMBOL(tape_std_mtunload);
EXPORT_SYMBOL(tape_std_mtcompression);
EXPORT_SYMBOL(tape_std_read_block);
-EXPORT_SYMBOL(tape_std_read_backward);
EXPORT_SYMBOL(tape_std_write_block);
EXPORT_SYMBOL(tape_std_process_eov);
diff --git a/drivers/s390/char/tape_std.h b/drivers/s390/char/tape_std.h
index dcc63ff587f9..2cf9f725b3b3 100644
--- a/drivers/s390/char/tape_std.h
+++ b/drivers/s390/char/tape_std.h
@@ -14,10 +14,9 @@
#include <asm/tape390.h>
/*
- * Biggest block size to handle. Currently 64K because we only build
- * channel programs without data chaining.
+ * Biggest block size of 256K to handle.
*/
-#define MAX_BLOCKSIZE 65535
+#define MAX_BLOCKSIZE 262144
/*
* The CCW commands for the Tape type of command.
@@ -97,10 +96,10 @@
#define SENSE_TAPE_POSITIONING 0x01
/* discipline functions */
-struct tape_request *tape_std_read_block(struct tape_device *, size_t);
+struct tape_request *tape_std_read_block(struct tape_device *);
void tape_std_read_backward(struct tape_device *device,
struct tape_request *request);
-struct tape_request *tape_std_write_block(struct tape_device *, size_t);
+struct tape_request *tape_std_write_block(struct tape_device *);
/* Some non-mtop commands. */
int tape_std_assign(struct tape_device *);
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 69899bb86b3e..bde6c9e59166 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -14,7 +14,6 @@
#include <linux/fs.h>
#include <linux/init.h>
-#include <linux/compat.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
@@ -204,10 +203,7 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int __user *argp;
session = file->private_data;
- if (is_compat_task())
- argp = compat_ptr(arg);
- else
- argp = (int __user *)arg;
+ argp = (int __user *)arg;
if (mutex_lock_interruptible(&session->mutex))
return -ERESTARTSYS;
switch (cmd) {
@@ -241,7 +237,6 @@ static const struct file_operations vmcp_fops = {
.read = vmcp_read,
.write = vmcp_write,
.unlocked_ioctl = vmcp_ioctl,
- .compat_ioctl = vmcp_ioctl,
};
static struct miscdevice vmcp_dev = {
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index e284eea331d7..383e7e2bd69f 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -11,8 +11,7 @@
*
*/
-#define KMSG_COMPONENT "vmlogrdr"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "vmlogrdr: " fmt
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 0fd918769a4b..e3e0e9f36527 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -9,8 +9,7 @@
* Frank Munzert <munzert@de.ibm.com>
*/
-#define KMSG_COMPONENT "vmur"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "vmur: " fmt
#include <linux/cdev.h>
#include <linux/slab.h>
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 33cebb91b933..b26b5fca6ce8 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -9,8 +9,7 @@
* Author(s): Michael Holzheu
*/
-#define KMSG_COMPONENT "zdump"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#define pr_fmt(fmt) "zdump: " fmt
#include <linux/init.h>
#include <linux/slab.h>