aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/Makefile2
-rw-r--r--drivers/s390/char/monwriter.c2
-rw-r--r--drivers/s390/char/raw3270.c4
-rw-r--r--drivers/s390/char/sclp.h4
-rw-r--r--drivers/s390/char/sclp_chp.c200
-rw-r--r--drivers/s390/char/sclp_cmd.c398
-rw-r--r--drivers/s390/char/sclp_config.c4
-rw-r--r--drivers/s390/char/sclp_cpi.c246
-rw-r--r--drivers/s390/char/sclp_cpi_sys.c400
-rw-r--r--drivers/s390/char/sclp_cpi_sys.h15
-rw-r--r--drivers/s390/char/sclp_info.c116
-rw-r--r--drivers/s390/char/sclp_rw.c2
-rw-r--r--drivers/s390/char/tape_3590.c2
-rw-r--r--drivers/s390/char/tape_block.c13
-rw-r--r--drivers/s390/char/tape_core.c2
-rw-r--r--drivers/s390/char/tape_proc.c2
-rw-r--r--drivers/s390/char/vmlogrdr.c2
-rw-r--r--drivers/s390/char/vmur.c2
-rw-r--r--drivers/s390/char/zcore.c2
19 files changed, 850 insertions, 568 deletions
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index 130de19916f2..7e73e39a1741 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -3,7 +3,7 @@
#
obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
- sclp_info.o sclp_config.o sclp_chp.o
+ sclp_cmd.o sclp_config.o sclp_cpi_sys.o
obj-$(CONFIG_TN3270) += raw3270.o
obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 20442fbf9346..a86c0534cd49 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -295,7 +295,7 @@ module_init(mon_init);
module_exit(mon_exit);
module_param_named(max_bufs, mon_max_bufs, int, 0644);
-MODULE_PARM_DESC(max_bufs, "Maximum number of sample monitor data buffers"
+MODULE_PARM_DESC(max_bufs, "Maximum number of sample monitor data buffers "
"that can be active at one time");
MODULE_AUTHOR("Melissa Howland <Melissa.Howland@us.ibm.com>");
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 8d1c64a24dec..0d98f1ff2edd 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -66,7 +66,7 @@ struct raw3270 {
static DEFINE_MUTEX(raw3270_mutex);
/* List of 3270 devices. */
-static struct list_head raw3270_devices = LIST_HEAD_INIT(raw3270_devices);
+static LIST_HEAD(raw3270_devices);
/*
* Flag to indicate if the driver has been registered. Some operations
@@ -1210,7 +1210,7 @@ struct raw3270_notifier {
void (*notifier)(int, int);
};
-static struct list_head raw3270_notifier = LIST_HEAD_INIT(raw3270_notifier);
+static LIST_HEAD(raw3270_notifier);
int raw3270_register_notifier(void (*notifier)(int, int))
{
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index c7318a125852..aa8186d18aee 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -56,8 +56,6 @@ typedef unsigned int sclp_cmdw_t;
#define SCLP_CMDW_READ_EVENT_DATA 0x00770005
#define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005
#define SCLP_CMDW_WRITE_EVENT_MASK 0x00780005
-#define SCLP_CMDW_READ_SCP_INFO 0x00020001
-#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
#define GDS_ID_MDSMU 0x1310
#define GDS_ID_MDSROUTEINFO 0x1311
@@ -83,6 +81,8 @@ extern u64 sclp_facilities;
#define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL)
#define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL)
+#define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL)
+#define SCLP_HAS_CPU_RECONFIG (sclp_facilities & 0x0400000000000000ULL)
struct gds_subvector {
u8 length;
diff --git a/drivers/s390/char/sclp_chp.c b/drivers/s390/char/sclp_chp.c
deleted file mode 100644
index c68f5e7e63a0..000000000000
--- a/drivers/s390/char/sclp_chp.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * drivers/s390/char/sclp_chp.c
- *
- * Copyright IBM Corp. 2007
- * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
- */
-
-#include <linux/types.h>
-#include <linux/gfp.h>
-#include <linux/errno.h>
-#include <linux/completion.h>
-#include <asm/sclp.h>
-#include <asm/chpid.h>
-
-#include "sclp.h"
-
-#define TAG "sclp_chp: "
-
-#define SCLP_CMDW_CONFIGURE_CHANNEL_PATH 0x000f0001
-#define SCLP_CMDW_DECONFIGURE_CHANNEL_PATH 0x000e0001
-#define SCLP_CMDW_READ_CHANNEL_PATH_INFORMATION 0x00030001
-
-static inline sclp_cmdw_t get_configure_cmdw(struct chp_id chpid)
-{
- return SCLP_CMDW_CONFIGURE_CHANNEL_PATH | chpid.id << 8;
-}
-
-static inline sclp_cmdw_t get_deconfigure_cmdw(struct chp_id chpid)
-{
- return SCLP_CMDW_DECONFIGURE_CHANNEL_PATH | chpid.id << 8;
-}
-
-static void chp_callback(struct sclp_req *req, void *data)
-{
- struct completion *completion = data;
-
- complete(completion);
-}
-
-struct chp_cfg_sccb {
- struct sccb_header header;
- u8 ccm;
- u8 reserved[6];
- u8 cssid;
-} __attribute__((packed));
-
-struct chp_cfg_data {
- struct chp_cfg_sccb sccb;
- struct sclp_req req;
- struct completion completion;
-} __attribute__((packed));
-
-static int do_configure(sclp_cmdw_t cmd)
-{
- struct chp_cfg_data *data;
- int rc;
-
- if (!SCLP_HAS_CHP_RECONFIG)
- return -EOPNOTSUPP;
- /* Prepare sccb. */
- data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
- if (!data)
- return -ENOMEM;
- data->sccb.header.length = sizeof(struct chp_cfg_sccb);
- data->req.command = cmd;
- data->req.sccb = &(data->sccb);
- data->req.status = SCLP_REQ_FILLED;
- data->req.callback = chp_callback;
- data->req.callback_data = &(data->completion);
- init_completion(&data->completion);
-
- /* Perform sclp request. */
- rc = sclp_add_request(&(data->req));
- if (rc)
- goto out;
- wait_for_completion(&data->completion);
-
- /* Check response .*/
- if (data->req.status != SCLP_REQ_DONE) {
- printk(KERN_WARNING TAG "configure channel-path request failed "
- "(status=0x%02x)\n", data->req.status);
- rc = -EIO;
- goto out;
- }
- switch (data->sccb.header.response_code) {
- case 0x0020:
- case 0x0120:
- case 0x0440:
- case 0x0450:
- break;
- default:
- printk(KERN_WARNING TAG "configure channel-path failed "
- "(cmd=0x%08x, response=0x%04x)\n", cmd,
- data->sccb.header.response_code);
- rc = -EIO;
- break;
- }
-out:
- free_page((unsigned long) data);
-
- return rc;
-}
-
-/**
- * sclp_chp_configure - perform configure channel-path sclp command
- * @chpid: channel-path ID
- *
- * Perform configure channel-path command sclp command for specified chpid.
- * Return 0 after command successfully finished, non-zero otherwise.
- */
-int sclp_chp_configure(struct chp_id chpid)
-{
- return do_configure(get_configure_cmdw(chpid));
-}
-
-/**
- * sclp_chp_deconfigure - perform deconfigure channel-path sclp command
- * @chpid: channel-path ID
- *
- * Perform deconfigure channel-path command sclp command for specified chpid
- * and wait for completion. On success return 0. Return non-zero otherwise.
- */
-int sclp_chp_deconfigure(struct chp_id chpid)
-{
- return do_configure(get_deconfigure_cmdw(chpid));
-}
-
-struct chp_info_sccb {
- struct sccb_header header;
- u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
- u8 standby[SCLP_CHP_INFO_MASK_SIZE];
- u8 configured[SCLP_CHP_INFO_MASK_SIZE];
- u8 ccm;
- u8 reserved[6];
- u8 cssid;
-} __attribute__((packed));
-
-struct chp_info_data {
- struct chp_info_sccb sccb;
- struct sclp_req req;
- struct completion completion;
-} __attribute__((packed));
-
-/**
- * sclp_chp_read_info - perform read channel-path information sclp command
- * @info: resulting channel-path information data
- *
- * Perform read channel-path information sclp command and wait for completion.
- * On success, store channel-path information in @info and return 0. Return
- * non-zero otherwise.
- */
-int sclp_chp_read_info(struct sclp_chp_info *info)
-{
- struct chp_info_data *data;
- int rc;
-
- if (!SCLP_HAS_CHP_INFO)
- return -EOPNOTSUPP;
- /* Prepare sccb. */
- data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
- if (!data)
- return -ENOMEM;
- data->sccb.header.length = sizeof(struct chp_info_sccb);
- data->req.command = SCLP_CMDW_READ_CHANNEL_PATH_INFORMATION;
- data->req.sccb = &(data->sccb);
- data->req.status = SCLP_REQ_FILLED;
- data->req.callback = chp_callback;
- data->req.callback_data = &(data->completion);
- init_completion(&data->completion);
-
- /* Perform sclp request. */
- rc = sclp_add_request(&(data->req));
- if (rc)
- goto out;
- wait_for_completion(&data->completion);
-
- /* Check response .*/
- if (data->req.status != SCLP_REQ_DONE) {
- printk(KERN_WARNING TAG "read channel-path info request failed "
- "(status=0x%02x)\n", data->req.status);
- rc = -EIO;
- goto out;
- }
- if (data->sccb.header.response_code != 0x0010) {
- printk(KERN_WARNING TAG "read channel-path info failed "
- "(response=0x%04x)\n", data->sccb.header.response_code);
- rc = -EIO;
- goto out;
- }
- memcpy(info->recognized, data->sccb.recognized,
- SCLP_CHP_INFO_MASK_SIZE);
- memcpy(info->standby, data->sccb.standby,
- SCLP_CHP_INFO_MASK_SIZE);
- memcpy(info->configured, data->sccb.configured,
- SCLP_CHP_INFO_MASK_SIZE);
-out:
- free_page((unsigned long) data);
-
- return rc;
-}
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
new file mode 100644
index 000000000000..b5c23396f8fe
--- /dev/null
+++ b/drivers/s390/char/sclp_cmd.c
@@ -0,0 +1,398 @@
+/*
+ * drivers/s390/char/sclp_cmd.c
+ *
+ * Copyright IBM Corp. 2007
+ * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
+ * Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
+ */
+
+#include <linux/completion.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <asm/chpid.h>
+#include <asm/sclp.h>
+#include "sclp.h"
+
+#define TAG "sclp_cmd: "
+
+#define SCLP_CMDW_READ_SCP_INFO 0x00020001
+#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
+
+struct read_info_sccb {
+ struct sccb_header header; /* 0-7 */
+ u16 rnmax; /* 8-9 */
+ u8 rnsize; /* 10 */
+ u8 _reserved0[24 - 11]; /* 11-15 */
+ u8 loadparm[8]; /* 24-31 */
+ u8 _reserved1[48 - 32]; /* 32-47 */
+ u64 facilities; /* 48-55 */
+ u8 _reserved2[84 - 56]; /* 56-83 */
+ u8 fac84; /* 84 */
+ u8 _reserved3[91 - 85]; /* 85-90 */
+ u8 flags; /* 91 */
+ u8 _reserved4[100 - 92]; /* 92-99 */
+ u32 rnsize2; /* 100-103 */
+ u64 rnmax2; /* 104-111 */
+ u8 _reserved5[4096 - 112]; /* 112-4095 */
+} __attribute__((packed, aligned(PAGE_SIZE)));
+
+static struct read_info_sccb __initdata early_read_info_sccb;
+static int __initdata early_read_info_sccb_valid;
+
+u64 sclp_facilities;
+static u8 sclp_fac84;
+
+static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
+{
+ int rc;
+
+ __ctl_set_bit(0, 9);
+ rc = sclp_service_call(cmd, sccb);
+ if (rc)
+ goto out;
+ __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
+ PSW_MASK_WAIT | PSW_DEFAULT_KEY);
+ local_irq_disable();
+out:
+ /* Contents of the sccb might have changed. */
+ barrier();
+ __ctl_clear_bit(0, 9);
+ return rc;
+}
+
+void __init sclp_read_info_early(void)
+{
+ int rc;
+ int i;
+ struct read_info_sccb *sccb;
+ sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
+ SCLP_CMDW_READ_SCP_INFO};
+
+ sccb = &early_read_info_sccb;
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ do {
+ memset(sccb, 0, sizeof(*sccb));
+ sccb->header.length = sizeof(*sccb);
+ sccb->header.control_mask[2] = 0x80;
+ rc = sclp_cmd_sync_early(commands[i], sccb);
+ } while (rc == -EBUSY);
+
+ if (rc)
+ break;
+ if (sccb->header.response_code == 0x10) {
+ early_read_info_sccb_valid = 1;
+ break;
+ }
+ if (sccb->header.response_code != 0x1f0)
+ break;
+ }
+}
+
+void __init sclp_facilities_detect(void)
+{
+ if (!early_read_info_sccb_valid)
+ return;
+ sclp_facilities = early_read_info_sccb.facilities;
+ sclp_fac84 = early_read_info_sccb.fac84;
+}
+
+unsigned long long __init sclp_memory_detect(void)
+{
+ unsigned long long memsize;
+ struct read_info_sccb *sccb;
+
+ if (!early_read_info_sccb_valid)
+ return 0;
+ sccb = &early_read_info_sccb;
+ if (sccb->rnsize)
+ memsize = sccb->rnsize << 20;
+ else
+ memsize = sccb->rnsize2 << 20;
+ if (sccb->rnmax)
+ memsize *= sccb->rnmax;
+ else
+ memsize *= sccb->rnmax2;
+ return memsize;
+}
+
+/*
+ * This function will be called after sclp_memory_detect(), which gets called
+ * early from early.c code. Therefore the sccb should have valid contents.
+ */
+void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
+{
+ struct read_info_sccb *sccb;
+
+ if (!early_read_info_sccb_valid)
+ return;
+ sccb = &early_read_info_sccb;
+ info->is_valid = 1;
+ if (sccb->flags & 0x2)
+ info->has_dump = 1;
+ memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
+}
+
+static void sclp_sync_callback(struct sclp_req *req, void *data)
+{
+ struct completion *completion = data;
+
+ complete(completion);
+}
+
+static int do_sync_request(sclp_cmdw_t cmd, void *sccb)
+{
+ struct completion completion;
+ struct sclp_req *request;
+ int rc;
+
+ request = kzalloc(sizeof(*request), GFP_KERNEL);
+ if (!request)
+ return -ENOMEM;
+ request->command = cmd;
+ request->sccb = sccb;
+ request->status = SCLP_REQ_FILLED;
+ request->callback = sclp_sync_callback;
+ request->callback_data = &completion;
+ init_completion(&completion);
+
+ /* Perform sclp request. */
+ rc = sclp_add_request(request);
+ if (rc)
+ goto out;
+ wait_for_completion(&completion);
+
+ /* Check response. */
+ if (request->status != SCLP_REQ_DONE) {
+ printk(KERN_WARNING TAG "sync request failed "
+ "(cmd=0x%08x, status=0x%02x)\n", cmd, request->status);
+ rc = -EIO;
+ }
+out:
+ kfree(request);
+ return rc;
+}
+
+/*
+ * CPU configuration related functions.
+ */
+
+#define SCLP_CMDW_READ_CPU_INFO 0x00010001
+#define SCLP_CMDW_CONFIGURE_CPU 0x00110001
+#define SCLP_CMDW_DECONFIGURE_CPU 0x00100001
+
+struct read_cpu_info_sccb {
+ struct sccb_header header;
+ u16 nr_configured;
+ u16 offset_configured;
+ u16 nr_standby;
+ u16 offset_standby;
+ u8 reserved[4096 - 16];
+} __attribute__((packed, aligned(PAGE_SIZE)));
+
+static void sclp_fill_cpu_info(struct sclp_cpu_info *info,
+ struct read_cpu_info_sccb *sccb)
+{
+ char *page = (char *) sccb;
+
+ memset(info, 0, sizeof(*info));
+ info->configured = sccb->nr_configured;
+ info->standby = sccb->nr_standby;
+ info->combined = sccb->nr_configured + sccb->nr_standby;
+ info->has_cpu_type = sclp_fac84 & 0x1;
+ memcpy(&info->cpu, page + sccb->offset_configured,
+ info->combined * sizeof(struct sclp_cpu_entry));
+}
+
+int sclp_get_cpu_info(struct sclp_cpu_info *info)
+{
+ int rc;
+ struct read_cpu_info_sccb *sccb;
+
+ if (!SCLP_HAS_CPU_INFO)
+ return -EOPNOTSUPP;
+ sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!sccb)
+ return -ENOMEM;
+ sccb->header.length = sizeof(*sccb);
+ rc = do_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb);
+ if (rc)
+ goto out;
+ if (sccb->header.response_code != 0x0010) {
+ printk(KERN_WARNING TAG "readcpuinfo failed "
+ "(response=0x%04x)\n", sccb->header.response_code);
+ rc = -EIO;
+ goto out;
+ }
+ sclp_fill_cpu_info(info, sccb);
+out:
+ free_page((unsigned long) sccb);
+ return rc;
+}
+
+struct cpu_configure_sccb {
+ struct sccb_header header;
+} __attribute__((packed, aligned(8)));
+
+static int do_cpu_configure(sclp_cmdw_t cmd)
+{
+ struct cpu_configure_sccb *sccb;
+ int rc;
+
+ if (!SCLP_HAS_CPU_RECONFIG)
+ return -EOPNOTSUPP;
+ /*
+ * This is not going to cross a page boundary since we force
+ * kmalloc to have a minimum alignment of 8 bytes on s390.
+ */
+ sccb = kzalloc(sizeof(*sccb), GFP_KERNEL | GFP_DMA);
+ if (!sccb)
+ return -ENOMEM;
+ sccb->header.length = sizeof(*sccb);
+ rc = do_sync_request(cmd, sccb);
+ if (rc)
+ goto out;
+ switch (sccb->header.response_code) {
+ case 0x0020:
+ case 0x0120:
+ break;
+ default:
+ printk(KERN_WARNING TAG "configure cpu failed (cmd=0x%08x, "
+ "response=0x%04x)\n", cmd, sccb->header.response_code);
+ rc = -EIO;
+ break;
+ }
+out:
+ kfree(sccb);
+ return rc;
+}
+
+int sclp_cpu_configure(u8 cpu)
+{
+ return do_cpu_configure(SCLP_CMDW_CONFIGURE_CPU | cpu << 8);
+}
+
+int sclp_cpu_deconfigure(u8 cpu)
+{
+ return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8);
+}
+
+/*
+ * Channel path configuration related functions.
+ */
+
+#define SCLP_CMDW_CONFIGURE_CHPATH 0x000f0001
+#define SCLP_CMDW_DECONFIGURE_CHPATH 0x000e0001
+#define SCLP_CMDW_READ_CHPATH_INFORMATION 0x00030001
+
+struct chp_cfg_sccb {
+ struct sccb_header header;
+ u8 ccm;
+ u8 reserved[6];
+ u8 cssid;
+} __attribute__((packed));
+
+static int do_chp_configure(sclp_cmdw_t cmd)
+{
+ struct chp_cfg_sccb *sccb;
+ int rc;
+
+ if (!SCLP_HAS_CHP_RECONFIG)
+ return -EOPNOTSUPP;
+ /* Prepare sccb. */
+ sccb = (struct chp_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!sccb)
+ return -ENOMEM;
+ sccb->header.length = sizeof(*sccb);
+ rc = do_sync_request(cmd, sccb);
+ if (rc)
+ goto out;
+ switch (sccb->header.response_code) {
+ case 0x0020:
+ case 0x0120:
+ case 0x0440:
+ case 0x0450:
+ break;
+ default:
+ printk(KERN_WARNING TAG "configure channel-path failed "
+ "(cmd=0x%08x, response=0x%04x)\n", cmd,
+ sccb->header.response_code);
+ rc = -EIO;
+ break;
+ }
+out:
+ free_page((unsigned long) sccb);
+ return rc;
+}
+
+/**
+ * sclp_chp_configure - perform configure channel-path sclp command
+ * @chpid: channel-path ID
+ *
+ * Perform configure channel-path command sclp command for specified chpid.
+ * Return 0 after command successfully finished, non-zero otherwise.
+ */
+int sclp_chp_configure(struct chp_id chpid)
+{
+ return do_chp_configure(SCLP_CMDW_CONFIGURE_CHPATH | chpid.id << 8);
+}
+
+/**
+ * sclp_chp_deconfigure - perform deconfigure channel-path sclp command
+ * @chpid: channel-path ID
+ *
+ * Perform deconfigure channel-path command sclp command for specified chpid
+ * and wait for completion. On success return 0. Return non-zero otherwise.
+ */
+int sclp_chp_deconfigure(struct chp_id chpid)
+{
+ return do_chp_configure(SCLP_CMDW_DECONFIGURE_CHPATH | chpid.id << 8);
+}
+
+struct chp_info_sccb {
+ struct sccb_header header;
+ u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
+ u8 standby[SCLP_CHP_INFO_MASK_SIZE];
+ u8 configured[SCLP_CHP_INFO_MASK_SIZE];
+ u8 ccm;
+ u8 reserved[6];
+ u8 cssid;
+} __attribute__((packed));
+
+/**
+ * sclp_chp_read_info - perform read channel-path information sclp command
+ * @info: resulting channel-path information data
+ *
+ * Perform read channel-path information sclp command and wait for completion.
+ * On success, store channel-path information in @info and return 0. Return
+ * non-zero otherwise.
+ */
+int sclp_chp_read_info(struct sclp_chp_info *info)
+{
+ struct chp_info_sccb *sccb;
+ int rc;
+
+ if (!SCLP_HAS_CHP_INFO)
+ return -EOPNOTSUPP;
+ /* Prepare sccb. */
+ sccb = (struct chp_info_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!sccb)
+ return -ENOMEM;
+ sccb->header.length = sizeof(*sccb);
+ rc = do_sync_request(SCLP_CMDW_READ_CHPATH_INFORMATION, sccb);
+ if (rc)
+ goto out;
+ if (sccb->header.response_code != 0x0010) {
+ printk(KERN_WARNING TAG "read channel-path info failed "
+ "(response=0x%04x)\n", sccb->header.response_code);
+ rc = -EIO;
+ goto out;
+ }
+ memcpy(info->recognized, sccb->recognized, SCLP_CHP_INFO_MASK_SIZE);
+ memcpy(info->standby, sccb->standby, SCLP_CHP_INFO_MASK_SIZE);
+ memcpy(info->configured, sccb->configured, SCLP_CHP_INFO_MASK_SIZE);
+out:
+ free_page((unsigned long) sccb);
+ return rc;
+}
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index 5322e5e54a98..9dc77f14fa52 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -29,12 +29,12 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
struct sys_device *sysdev;
printk(KERN_WARNING TAG "cpu capability changed.\n");
- lock_cpu_hotplug();
+ get_online_cpus();
for_each_online_cpu(cpu) {
sysdev = get_cpu_sysdev(cpu);
kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
}
- unlock_cpu_hotplug();
+ put_online_cpus();
}
static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c
index 82a13d9fdfe4..5716487b8c9d 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -1,255 +1,41 @@
/*
- * Author: Martin Peschke <mpeschke@de.ibm.com>
- * Copyright (C) 2001 IBM Entwicklung GmbH, IBM Corporation
+ * drivers/s390/char/sclp_cpi.c
+ * SCLP control programm identification
*
- * SCLP Control-Program Identification.
+ * Copyright IBM Corp. 2001, 2007
+ * Author(s): Martin Peschke <mpeschke@de.ibm.com>
+ * Michael Ernst <mernst@de.ibm.com>
*/
-#include <linux/version.h>
#include <linux/kmod.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <asm/ebcdic.h>
-#include <asm/semaphore.h>
-
-#include "sclp.h"
-#include "sclp_rw.h"
-
-#define CPI_LENGTH_SYSTEM_TYPE 8
-#define CPI_LENGTH_SYSTEM_NAME 8
-#define CPI_LENGTH_SYSPLEX_NAME 8
-
-struct cpi_evbuf {
- struct evbuf_header header;
- u8 id_format;
- u8 reserved0;
- u8 system_type[CPI_LENGTH_SYSTEM_TYPE];
- u64 reserved1;
- u8 system_name[CPI_LENGTH_SYSTEM_NAME];
- u64 reserved2;
- u64 system_level;
- u64 reserved3;
- u8 sysplex_name[CPI_LENGTH_SYSPLEX_NAME];
- u8 reserved4[16];
-} __attribute__((packed));
-
-struct cpi_sccb {
- struct sccb_header header;
- struct cpi_evbuf cpi_evbuf;
-} __attribute__((packed));
-
-/* Event type structure for write message and write priority message */
-static struct sclp_register sclp_cpi_event =
-{
- .send_mask = EVTYP_CTLPROGIDENT_MASK
-};
+#include <linux/version.h>
+#include "sclp_cpi_sys.h"
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Identify this operating system instance "
+ "to the System z hardware");
+MODULE_AUTHOR("Martin Peschke <mpeschke@de.ibm.com>, "
+ "Michael Ernst <mernst@de.ibm.com>");
-MODULE_AUTHOR(
- "Martin Peschke, IBM Deutschland Entwicklung GmbH "
- "<mpeschke@de.ibm.com>");
-
-MODULE_DESCRIPTION(
- "identify this operating system instance to the S/390 "
- "or zSeries hardware");
+static char *system_name = "";
+static char *sysplex_name = "";
-static char *system_name = NULL;
module_param(system_name, charp, 0);
MODULE_PARM_DESC(system_name, "e.g. hostname - max. 8 characters");
-
-static char *sysplex_name = NULL;
-#ifdef ALLOW_SYSPLEX_NAME
module_param(sysplex_name, charp, 0);
MODULE_PARM_DESC(sysplex_name, "if applicable - max. 8 characters");
-#endif
-
-/* use default value for this field (as well as for system level) */
-static char *system_type = "LINUX";
-static int
-cpi_check_parms(void)
+static int __init cpi_module_init(void)
{
- /* reject if no system type specified */
- if (!system_type) {
- printk("cpi: bug: no system type specified\n");
- return -EINVAL;
- }
-
- /* reject if system type larger than 8 characters */
- if (strlen(system_type) > CPI_LENGTH_SYSTEM_NAME) {
- printk("cpi: bug: system type has length of %li characters - "
- "only %i characters supported\n",
- strlen(system_type), CPI_LENGTH_SYSTEM_TYPE);
- return -EINVAL;
- }
-
- /* reject if no system name specified */
- if (!system_name) {
- printk("cpi: no system name specified\n");
- return -EINVAL;
- }
-
- /* reject if system name larger than 8 characters */
- if (strlen(system_name) > CPI_LENGTH_SYSTEM_NAME) {
- printk("cpi: system name has length of %li characters - "
- "only %i characters supported\n",
- strlen(system_name), CPI_LENGTH_SYSTEM_NAME);
- return -EINVAL;
- }
-
- /* reject if specified sysplex name larger than 8 characters */
- if (sysplex_name && strlen(sysplex_name) > CPI_LENGTH_SYSPLEX_NAME) {
- printk("cpi: sysplex name has length of %li characters"
- " - only %i characters supported\n",
- strlen(sysplex_name), CPI_LENGTH_SYSPLEX_NAME);
- return -EINVAL;
- }
- return 0;
+ return sclp_cpi_set_data(system_name, sysplex_name, "LINUX",
+ LINUX_VERSION_CODE);
}
-static void
-cpi_callback(struct sclp_req *req, void *data)
-{
- struct semaphore *sem;
-
- sem = (struct semaphore *) data;
- up(sem);
-}
-
-static struct sclp_req *
-cpi_prepare_req(void)
-{
- struct sclp_req *req;
- struct cpi_sccb *sccb;
- struct cpi_evbuf *evb;
-
- req = kmalloc(sizeof(struct sclp_req), GFP_KERNEL);
- if (req == NULL)
- return ERR_PTR(-ENOMEM);
- sccb = (struct cpi_sccb *) __get_free_page(GFP_KERNEL | GFP_DMA);
- if (sccb == NULL) {
- kfree(req);
- return ERR_PTR(-ENOMEM);
- }
- memset(sccb, 0, sizeof(struct cpi_sccb));
-
- /* setup SCCB for Control-Program Identification */
- sccb->header.length = sizeof(struct cpi_sccb);
- sccb->cpi_evbuf.header.length = sizeof(struct cpi_evbuf);
- sccb->cpi_evbuf.header.type = 0x0B;
- evb = &sccb->cpi_evbuf;
-
- /* set system type */
- memset(evb->system_type, ' ', CPI_LENGTH_SYSTEM_TYPE);
- memcpy(evb->system_type, system_type, strlen(system_type));
- sclp_ascebc_str(evb->system_type, CPI_LENGTH_SYSTEM_TYPE);
- EBC_TOUPPER(evb->system_type, CPI_LENGTH_SYSTEM_TYPE);
-
- /* set system name */
- memset(evb->system_name, ' ', CPI_LENGTH_SYSTEM_NAME);
- memcpy(evb->system_name, system_name, strlen(system_name));
- sclp_ascebc_str(evb->system_name, CPI_LENGTH_SYSTEM_NAME);
- EBC_TOUPPER(evb->system_name, CPI_LENGTH_SYSTEM_NAME);
-
- /* set system level */
- evb->system_level = LINUX_VERSION_CODE;
-
- /* set sysplex name */
- if (sysplex_name) {
- memset(evb->sysplex_name, ' ', CPI_LENGTH_SYSPLEX_NAME);
- memcpy(evb->sysplex_name, sysplex_name, strlen(sysplex_name));
- sclp_ascebc_str(evb->sysplex_name, CPI_LENGTH_SYSPLEX_NAME);
- EBC_TOUPPER(evb->sysplex_name, CPI_LENGTH_SYSPLEX_NAME);
- }
-
- /* prepare request data structure presented to SCLP driver */
- req->command = SCLP_CMDW_WRITE_EVENT_DATA;
- req->sccb = sccb;
- req->status = SCLP_REQ_FILLED;
- req->callback = cpi_callback;
- return req;
-}
-
-static void
-cpi_free_req(struct sclp_req *req)
-{
- free_page((unsigned long) req->sccb);
- kfree(req);
-}
-
-static int __init
-cpi_module_init(void)
-{
- struct semaphore sem;
- struct sclp_req *req;
- int rc;
-
- rc = cpi_check_parms();
- if (rc)
- return rc;
-
- rc = sclp_register(&sclp_cpi_event);
- if (rc) {
- /* could not register sclp event. Die. */
- printk(KERN_WARNING "cpi: could not register to hardware "
- "console.\n");
- return -EINVAL;
- }
- if (!(sclp_cpi_event.sclp_send_mask & EVTYP_CTLPROGIDENT_MASK)) {
- printk(KERN_WARNING "cpi: no control program identification "
- "support\n");
- sclp_unregister(&sclp_cpi_event);
- return -EOPNOTSUPP;
- }
-
- req = cpi_prepare_req();
- if (IS_ERR(req)) {
- printk(KERN_WARNING "cpi: couldn't allocate request\n");
- sclp_unregister(&sclp_cpi_event);
- return PTR_ERR(req);
- }
-
- /* Prepare semaphore */
- sema_init(&sem, 0);
- req->callback_data = &sem;
- /* Add request to sclp queue */
- rc = sclp_add_request(req);
- if (rc) {
- printk(KERN_WARNING "cpi: could not start request\n");
- cpi_free_req(req);
- sclp_unregister(&sclp_cpi_event);
- return rc;
- }
- /* make "insmod" sleep until callback arrives */
- down(&sem);
-
- rc = ((struct cpi_sccb *) req->sccb)->header.response_code;
- if (rc != 0x0020) {
- printk(KERN_WARNING "cpi: failed with response code 0x%x\n",
- rc);
- rc = -ECOMM;
- } else
- rc = 0;
-
- cpi_free_req(req);
- sclp_unregister(&sclp_cpi_event);
-
- return rc;
-}
-
-
static void __exit cpi_module_exit(void)
{
}
-
-/* declare driver module init/cleanup functions */
module_init(cpi_module_init);
module_exit(cpi_module_exit);
-
diff --git a/drivers/s390/char/sclp_cpi_sys.c b/drivers/s390/char/sclp_cpi_sys.c
new file mode 100644
index 000000000000..41617032afdc
--- /dev/null
+++ b/drivers/s390/char/sclp_cpi_sys.c
@@ -0,0 +1,400 @@
+/*
+ * drivers/s390/char/sclp_cpi_sys.c
+ * SCLP control program identification sysfs interface
+ *
+ * Copyright IBM Corp. 2001, 2007
+ * Author(s): Martin Peschke <mpeschke@de.ibm.com>
+ * Michael Ernst <mernst@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/device.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/kmod.h>
+#include <linux/timer.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/completion.h>
+#include <asm/ebcdic.h>
+#include <asm/sclp.h>
+#include "sclp.h"
+#include "sclp_rw.h"
+#include "sclp_cpi_sys.h"
+
+#define CPI_LENGTH_NAME 8
+#define CPI_LENGTH_LEVEL 16
+
+struct cpi_evbuf {
+ struct evbuf_header header;
+ u8 id_format;
+ u8 reserved0;
+ u8 system_type[CPI_LENGTH_NAME];
+ u64 reserved1;
+ u8 system_name[CPI_LENGTH_NAME];
+ u64 reserved2;
+ u64 system_level;
+ u64 reserved3;
+ u8 sysplex_name[CPI_LENGTH_NAME];
+ u8 reserved4[16];
+} __attribute__((packed));
+
+struct cpi_sccb {
+ struct sccb_header header;
+ struct cpi_evbuf cpi_evbuf;
+} __attribute__((packed));
+
+static struct sclp_register sclp_cpi_event = {
+ .send_mask = EVTYP_CTLPROGIDENT_MASK,
+};
+
+static char system_name[CPI_LENGTH_NAME + 1];
+static char sysplex_name[CPI_LENGTH_NAME + 1];
+static char system_type[CPI_LENGTH_NAME + 1];
+static u64 system_level;
+
+static void set_data(char *field, char *data)
+{
+ memset(field, ' ', CPI_LENGTH_NAME);
+ memcpy(field, data, strlen(data));
+ sclp_ascebc_str(field, CPI_LENGTH_NAME);
+}
+
+static void cpi_callback(struct sclp_req *req, void *data)
+{
+ struct completion *completion = data;
+
+ complete(completion);
+}
+
+static struct sclp_req *cpi_prepare_req(void)
+{
+ struct sclp_req *req;
+ struct cpi_sccb *sccb;
+ struct cpi_evbuf *evb;
+
+ req = kzalloc(sizeof(struct sclp_req), GFP_KERNEL);
+ if (!req)
+ return ERR_PTR(-ENOMEM);
+ sccb = (struct cpi_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!sccb) {
+ kfree(req);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* setup SCCB for Control-Program Identification */
+ sccb->header.length = sizeof(struct cpi_sccb);
+ sccb->cpi_evbuf.header.length = sizeof(struct cpi_evbuf);
+ sccb->cpi_evbuf.header.type = 0x0b;
+ evb = &sccb->cpi_evbuf;
+
+ /* set system type */
+ set_data(evb->system_type, system_type);
+
+ /* set system name */
+ set_data(evb->system_name, system_name);
+
+ /* set sytem level */
+ evb->system_level = system_level;
+
+ /* set sysplex name */
+ set_data(evb->sysplex_name, sysplex_name);
+
+ /* prepare request data structure presented to SCLP driver */
+ req->command = SCLP_CMDW_WRITE_EVENT_DATA;
+ req->sccb = sccb;
+ req->status = SCLP_REQ_FILLED;
+ req->callback = cpi_callback;
+ return req;
+}
+
+static void cpi_free_req(struct sclp_req *req)
+{
+ free_page((unsigned long) req->sccb);
+ kfree(req);
+}
+
+static int cpi_req(void)
+{
+ struct completion completion;
+ struct sclp_req *req;
+ int rc;
+ int response;
+
+ rc = sclp_register(&sclp_cpi_event);
+ if (rc) {
+ printk(KERN_WARNING "cpi: could not register "
+ "to hardware console.\n");
+ goto out;
+ }
+ if (!(sclp_cpi_event.sclp_send_mask & EVTYP_CTLPROGIDENT_MASK)) {
+ printk(KERN_WARNING "cpi: no control program "
+ "identification support\n");
+ rc = -EOPNOTSUPP;
+ goto out_unregister;
+ }
+
+ req = cpi_prepare_req();
+ if (IS_ERR(req)) {
+ printk(KERN_WARNING "cpi: could not allocate request\n");
+ rc = PTR_ERR(req);
+ goto out_unregister;
+ }
+
+ init_completion(&completion);
+ req->callback_data = &completion;
+
+ /* Add request to sclp queue */
+ rc = sclp_add_request(req);
+ if (rc) {
+ printk(KERN_WARNING "cpi: could not start request\n");
+ goto out_free_req;
+ }
+
+ wait_for_completion(&completion);
+
+ if (req->status != SCLP_REQ_DONE) {
+ printk(KERN_WARNING "cpi: request failed (status=0x%02x)\n",
+ req->status);
+ rc = -EIO;
+ goto out_free_req;
+ }
+
+ response = ((struct cpi_sccb *) req->sccb)->header.response_code;
+ if (response != 0x0020) {
+ printk(KERN_WARNING "cpi: failed with "
+ "response code 0x%x\n", response);
+ rc = -EIO;
+ }
+
+out_free_req:
+ cpi_free_req(req);
+
+out_unregister:
+ sclp_unregister(&sclp_cpi_event);
+
+out:
+ return rc;
+}
+
+static int check_string(const char *attr, const char *str)
+{
+ size_t len;
+ size_t i;
+
+ len = strlen(str);
+
+ if ((len > 0) && (str[len - 1] == '\n'))
+ len--;
+
+ if (len > CPI_LENGTH_NAME)
+ return -EINVAL;
+
+ for (i = 0; i < len ; i++) {
+ if (isalpha(str[i]) || isdigit(str[i]) ||
+ strchr("$@# ", str[i]))
+ continue;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void set_string(char *attr, const char *value)
+{
+ size_t len;
+ size_t i;
+
+ len = strlen(value);
+
+ if ((len > 0) && (value[len - 1] == '\n'))
+ len--;
+
+ for (i = 0; i < CPI_LENGTH_NAME; i++) {
+ if (i < len)
+ attr[i] = toupper(value[i]);
+ else
+ attr[i] = ' ';
+ }
+}
+
+static ssize_t system_name_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *page)
+{
+ return snprintf(page, PAGE_SIZE, "%s\n", system_name);
+}
+
+static ssize_t system_name_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ int rc;
+
+ rc = check_string("system_name", buf);
+ if (rc)
+ return rc;
+
+ set_string(system_name, buf);
+
+ return len;
+}
+
+static struct kobj_attribute system_name_attr =
+ __ATTR(system_name, 0644, system_name_show, system_name_store);
+
+static ssize_t sysplex_name_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *page)
+{
+ return snprintf(page, PAGE_SIZE, "%s\n", sysplex_name);
+}
+
+static ssize_t sysplex_name_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ int rc;
+
+ rc = check_string("sysplex_name", buf);
+ if (rc)
+ return rc;
+
+ set_string(sysplex_name, buf);
+
+ return len;
+}
+
+static struct kobj_attribute sysplex_name_attr =
+ __ATTR(sysplex_name, 0644, sysplex_name_show, sysplex_name_store);
+
+static ssize_t system_type_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *page)
+{
+ return snprintf(page, PAGE_SIZE, "%s\n", system_type);
+}
+
+static ssize_t system_type_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ int rc;
+
+ rc = check_string("system_type", buf);
+ if (rc)
+ return rc;
+
+ set_string(system_type, buf);
+
+ return len;
+}
+
+static struct kobj_attribute system_type_attr =
+ __ATTR(system_type, 0644, system_type_show, system_type_store);
+
+static ssize_t system_level_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *page)
+{
+ unsigned long long level = system_level;
+
+ return snprintf(page, PAGE_SIZE, "%#018llx\n", level);
+}
+
+static ssize_t system_level_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ unsigned long long level;
+ char *endp;
+
+ level = simple_strtoull(buf, &endp, 16);
+
+ if (endp == buf)
+ return -EINVAL;
+ if (*endp == '\n')
+ endp++;
+ if (*endp)
+ return -EINVAL;
+
+ system_level = level;
+
+ return len;
+}
+
+static struct kobj_attribute system_level_attr =
+ __ATTR(system_level, 0644, system_level_show, system_level_store);
+
+static ssize_t set_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t len)
+{
+ int rc;
+
+ rc = cpi_req();
+ if (rc)
+ return rc;
+
+ return len;
+}
+
+static struct kobj_attribute set_attr = __ATTR(set, 0200, NULL, set_store);
+
+static struct attribute *cpi_attrs[] = {
+ &system_name_attr.attr,
+ &sysplex_name_attr.attr,
+ &system_type_attr.attr,
+ &system_level_attr.attr,
+ &set_attr.attr,
+ NULL,
+};
+
+static struct attribute_group cpi_attr_group = {
+ .attrs = cpi_attrs,
+};
+
+static struct kset *cpi_kset;
+
+int sclp_cpi_set_data(const char *system, const char *sysplex, const char *type,
+ const u64 level)
+{
+ int rc;
+
+ rc = check_string("system_name", system);
+ if (rc)
+ return rc;
+ rc = check_string("sysplex_name", sysplex);
+ if (rc)
+ return rc;
+ rc = check_string("system_type", type);
+ if (rc)
+ return rc;
+
+ set_string(system_name, system);
+ set_string(sysplex_name, sysplex);
+ set_string(system_type, type);
+ system_level = level;
+
+ return cpi_req();
+}
+EXPORT_SYMBOL(sclp_cpi_set_data);
+
+static int __init cpi_init(void)
+{
+ int rc;
+
+ cpi_kset = kset_create_and_add("cpi", NULL, firmware_kobj);
+ if (!cpi_kset)
+ return -ENOMEM;
+
+ rc = sysfs_create_group(&cpi_kset->kobj, &cpi_attr_group);
+ if (rc)
+ kset_unregister(cpi_kset);
+
+ return rc;
+}
+
+__initcall(cpi_init);
diff --git a/drivers/s390/char/sclp_cpi_sys.h b/drivers/s390/char/sclp_cpi_sys.h
new file mode 100644
index 000000000000..deef3e6ff496
--- /dev/null
+++ b/drivers/s390/char/sclp_cpi_sys.h
@@ -0,0 +1,15 @@
+/*
+ * drivers/s390/char/sclp_cpi_sys.h
+ * SCLP control program identification sysfs interface
+ *
+ * Copyright IBM Corp. 2007
+ * Author(s): Michael Ernst <mernst@de.ibm.com>
+ */
+
+#ifndef __SCLP_CPI_SYS_H__
+#define __SCLP_CPI_SYS_H__
+
+int sclp_cpi_set_data(const char *system, const char *sysplex,
+ const char *type, u64 level);
+
+#endif /* __SCLP_CPI_SYS_H__ */
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
deleted file mode 100644
index a1136e052750..000000000000
--- a/drivers/s390/char/sclp_info.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * drivers/s390/char/sclp_info.c
- *
- * Copyright IBM Corp. 2007
- * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
- */
-
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <asm/sclp.h>
-#include "sclp.h"
-
-struct sclp_readinfo_sccb {
- struct sccb_header header; /* 0-7 */
- u16 rnmax; /* 8-9 */
- u8 rnsize; /* 10 */
- u8 _reserved0[24 - 11]; /* 11-23 */
- u8 loadparm[8]; /* 24-31 */
- u8 _reserved1[48 - 32]; /* 32-47 */
- u64 facilities; /* 48-55 */
- u8 _reserved2[91 - 56]; /* 56-90 */
- u8 flags; /* 91 */
- u8 _reserved3[100 - 92]; /* 92-99 */
- u32 rnsize2; /* 100-103 */
- u64 rnmax2; /* 104-111 */
- u8 _reserved4[4096 - 112]; /* 112-4095 */
-} __attribute__((packed, aligned(4096)));
-
-static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
-static int __initdata early_readinfo_sccb_valid;
-
-u64 sclp_facilities;
-
-void __init sclp_readinfo_early(void)
-{
- int ret;
- int i;
- struct sclp_readinfo_sccb *sccb;
- sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
- SCLP_CMDW_READ_SCP_INFO};
-
- /* Enable service signal subclass mask. */
- __ctl_set_bit(0, 9);
- sccb = &early_readinfo_sccb;
- for (i = 0; i < ARRAY_SIZE(commands); i++) {
- do {
- memset(sccb, 0, sizeof(*sccb));
- sccb->header.length = sizeof(*sccb);
- sccb->header.control_mask[2] = 0x80;
- ret = sclp_service_call(commands[i], sccb);
- } while (ret == -EBUSY);
-
- if (ret)
- break;
- __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
- PSW_MASK_WAIT | PSW_DEFAULT_KEY);
- local_irq_disable();
- /*
- * Contents of the sccb might have changed
- * therefore a barrier is needed.
- */
- barrier();
- if (sccb->header.response_code == 0x10) {
- early_readinfo_sccb_valid = 1;
- break;
- }
- if (sccb->header.response_code != 0x1f0)
- break;
- }
- /* Disable service signal subclass mask again. */
- __ctl_clear_bit(0, 9);
-}
-
-void __init sclp_facilities_detect(void)
-{
- if (!early_readinfo_sccb_valid)
- return;
- sclp_facilities = early_readinfo_sccb.facilities;
-}
-
-unsigned long long __init sclp_memory_detect(void)
-{
- unsigned long long memsize;
- struct sclp_readinfo_sccb *sccb;
-
- if (!early_readinfo_sccb_valid)
- return 0;
- sccb = &early_readinfo_sccb;
- if (sccb->rnsize)
- memsize = sccb->rnsize << 20;
- else
- memsize = sccb->rnsize2 << 20;
- if (sccb->rnmax)
- memsize *= sccb->rnmax;
- else
- memsize *= sccb->rnmax2;
- return memsize;
-}
-
-/*
- * This function will be called after sclp_memory_detect(), which gets called
- * early from early.c code. Therefore the sccb should have valid contents.
- */
-void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
-{
- struct sclp_readinfo_sccb *sccb;
-
- if (!early_readinfo_sccb_valid)
- return;
- sccb = &early_readinfo_sccb;
- info->is_valid = 1;
- if (sccb->flags & 0x2)
- info->has_dump = 1;
- memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
-}
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index d6b06ab81188..ad7195d3de0c 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -76,7 +76,7 @@ sclp_make_buffer(void *page, unsigned short columns, unsigned short htab)
}
/*
- * Return a pointer to the orignal page that has been used to create
+ * Return a pointer to the original page that has been used to create
* the buffer.
*/
void *
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index da25f8e24152..8246ef3ab095 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -1495,7 +1495,7 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
device->cdev->dev.bus_id);
return tape_3590_erp_basic(device, request, irb, -EPERM);
case 0x8013:
- PRINT_WARN("(%s): Another host has priviliged access to the "
+ PRINT_WARN("(%s): Another host has privileged access to the "
"tape device\n", device->cdev->dev.bus_id);
PRINT_WARN("(%s): To solve the problem unload the current "
"cartridge!\n", device->cdev->dev.bus_id);
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index eeb92e2ed0cc..ddc4a114e7f4 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -74,11 +74,10 @@ tapeblock_trigger_requeue(struct tape_device *device)
* Post finished request.
*/
static void
-tapeblock_end_request(struct request *req, int uptodate)
+tapeblock_end_request(struct request *req, int error)
{
- if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
+ if (__blk_end_request(req, error, blk_rq_bytes(req)))
BUG();
- end_that_request_last(req, uptodate);
}
static void
@@ -91,7 +90,7 @@ __tapeblock_end_request(struct tape_request *ccw_req, void *data)
device = ccw_req->device;
req = (struct request *) data;
- tapeblock_end_request(req, ccw_req->rc == 0);
+ tapeblock_end_request(req, (ccw_req->rc == 0) ? 0 : -EIO);
if (ccw_req->rc == 0)
/* Update position. */
device->blk_data.block_position =
@@ -119,7 +118,7 @@ tapeblock_start_request(struct tape_device *device, struct request *req)
ccw_req = device->discipline->bread(device, req);
if (IS_ERR(ccw_req)) {
DBF_EVENT(1, "TBLOCK: bread failed\n");
- tapeblock_end_request(req, 0);
+ tapeblock_end_request(req, -EIO);
return PTR_ERR(ccw_req);
}
ccw_req->callback = __tapeblock_end_request;
@@ -132,7 +131,7 @@ tapeblock_start_request(struct tape_device *device, struct request *req)
* Start/enqueueing failed. No retries in
* this case.
*/
- tapeblock_end_request(req, 0);
+ tapeblock_end_request(req, -EIO);
device->discipline->free_bread(ccw_req);
}
@@ -177,7 +176,7 @@ tapeblock_requeue(struct work_struct *work) {
if (rq_data_dir(req) == WRITE) {
DBF_EVENT(1, "TBLOCK: Rejecting write request\n");
blkdev_dequeue_request(req);
- tapeblock_end_request(req, 0);
+ tapeblock_end_request(req, -EIO);
continue;
}
spin_unlock_irq(&device->blk_data.request_queue_lock);
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 2fae6338ee1c..7ad8cf157641 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -37,7 +37,7 @@ static void tape_long_busy_timeout(unsigned long data);
* we can assign the devices to minor numbers of the same major
* The list is protected by the rwlock
*/
-static struct list_head tape_device_list = LIST_HEAD_INIT(tape_device_list);
+static LIST_HEAD(tape_device_list);
static DEFINE_RWLOCK(tape_device_lock);
/*
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index cea49f001f89..c9b96d51b28f 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -97,7 +97,7 @@ static void tape_proc_stop(struct seq_file *m, void *v)
{
}
-static struct seq_operations tape_proc_seq = {
+static const struct seq_operations tape_proc_seq = {
.start = tape_proc_start,
.next = tape_proc_next,
.stop = tape_proc_stop,
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index e0c4c508e121..d364e0bfae12 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -683,7 +683,7 @@ static int vmlogrdr_register_driver(void)
/* Register with iucv driver */
ret = iucv_register(&vmlogrdr_iucv_handler, 1);
if (ret) {
- printk (KERN_ERR "vmlogrdr: failed to register with"
+ printk (KERN_ERR "vmlogrdr: failed to register with "
"iucv driver\n");
goto out;
}
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index d70a6e65bf14..7689b500a104 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -759,7 +759,7 @@ static loff_t ur_llseek(struct file *file, loff_t offset, int whence)
return newpos;
}
-static struct file_operations ur_fops = {
+static const struct file_operations ur_fops = {
.owner = THIS_MODULE,
.open = ur_open,
.release = ur_release,
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 7073daf77981..f523501e6e6c 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -470,7 +470,7 @@ static loff_t zcore_lseek(struct file *file, loff_t offset, int orig)
return rc;
}
-static struct file_operations zcore_fops = {
+static const struct file_operations zcore_fops = {
.owner = THIS_MODULE,
.llseek = zcore_lseek,
.read = zcore_read,