summaryrefslogtreecommitdiff
path: root/drivers/s390/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/Makefile16
-rw-r--r--drivers/s390/char/con3215.c14
-rw-r--r--drivers/s390/char/con3270.c2
-rw-r--r--drivers/s390/char/fs3270.c1
-rw-r--r--drivers/s390/char/keyboard.c4
-rw-r--r--drivers/s390/char/monreader.c2
-rw-r--r--drivers/s390/char/monwriter.c2
-rw-r--r--drivers/s390/char/raw3270.c2
-rw-r--r--drivers/s390/char/sclp.c32
-rw-r--r--drivers/s390/char/sclp.h63
-rw-r--r--drivers/s390/char/sclp_cmd.c25
-rw-r--r--drivers/s390/char/sclp_ctl.c4
-rw-r--r--drivers/s390/char/sclp_early.c174
-rw-r--r--drivers/s390/char/sclp_early_core.c208
-rw-r--r--drivers/s390/char/sclp_quiesce.c4
-rw-r--r--drivers/s390/char/sclp_rw.c2
-rw-r--r--drivers/s390/char/sclp_tty.c5
-rw-r--r--drivers/s390/char/sclp_vt220.c2
-rw-r--r--drivers/s390/char/tape_char.c2
-rw-r--r--drivers/s390/char/tty3270.c2
-rw-r--r--drivers/s390/char/vmcp.c2
-rw-r--r--drivers/s390/char/vmlogrdr.c4
-rw-r--r--drivers/s390/char/vmur.c2
-rw-r--r--drivers/s390/char/zcore.c27
24 files changed, 381 insertions, 220 deletions
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index 41e28b23b26a..0c443e26835d 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -2,9 +2,23 @@
# S/390 character devices
#
+ifdef CONFIG_FUNCTION_TRACER
+# Do not trace early setup code
+CFLAGS_REMOVE_sclp_early_core.o = $(CC_FLAGS_FTRACE)
+endif
+
+GCOV_PROFILE_sclp_early_core.o := n
+KCOV_INSTRUMENT_sclp_early_core.o := n
+UBSAN_SANITIZE_sclp_early_core.o := n
+
+ifneq ($(CC_FLAGS_MARCH),-march=z900)
+CFLAGS_REMOVE_sclp_early_core.o += $(CC_FLAGS_MARCH)
+CFLAGS_sclp_early_core.o += -march=z900
+endif
+
obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
sclp_cmd.o sclp_config.o sclp_cpi_sys.o sclp_ocf.o sclp_ctl.o \
- sclp_early.o
+ sclp_early.o sclp_early_core.o
obj-$(CONFIG_TN3270) += raw3270.o
obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 931d10e86837..9ec4ae056158 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -9,7 +9,6 @@
* Dan Morrison, IBM Corporation <dmorriso@cse.buffalo.edu>
*/
-#include <linux/module.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/tty.h>
@@ -26,7 +25,7 @@
#include <asm/cio.h>
#include <asm/io.h>
#include <asm/ebcdic.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/delay.h>
#include <asm/cpcmd.h>
#include <asm/setup.h>
@@ -1215,13 +1214,4 @@ static int __init tty3215_init(void)
tty3215_driver = driver;
return 0;
}
-
-static void __exit tty3215_exit(void)
-{
- tty_unregister_driver(tty3215_driver);
- put_tty_driver(tty3215_driver);
- ccw_driver_unregister(&raw3215_ccw_driver);
-}
-
-module_init(tty3215_init);
-module_exit(tty3215_exit);
+device_initcall(tty3215_init);
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index 285b4006f44b..8522cfce5b4e 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -31,7 +31,7 @@
static struct raw3270_fn con3270_fn;
-static bool auto_update = 1;
+static bool auto_update = true;
module_param(auto_update, bool, 0);
/*
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 85eca1cef063..c4518168fd02 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -12,6 +12,7 @@
#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>
#include <linux/slab.h>
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 7b9c50aa4cc9..ba0e4f93503d 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -7,14 +7,14 @@
*/
#include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/sysrq.h>
#include <linux/consolemap.h>
#include <linux/kbd_kern.h>
#include <linux/kbd_diacr.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "keyboard.h"
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index ebdeaa53182d..027ac6ae5eea 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -23,7 +23,7 @@
#include <linux/device.h>
#include <linux/slab.h>
#include <net/iucv/iucv.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/ebcdic.h>
#include <asm/extmem.h>
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 9b5d1138b2e2..571a7e352755 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -21,7 +21,7 @@
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/ebcdic.h>
#include <asm/io.h>
#include <asm/appldata.h>
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index a2da898ce90f..710f2292911d 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -82,7 +82,7 @@ static LIST_HEAD(raw3270_devices);
static int raw3270_registered;
/* Module parameters */
-static bool tubxcorrect = 0;
+static bool tubxcorrect;
module_param(tubxcorrect, bool, 0);
/*
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 272898225dbb..9c471ea1b99c 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -94,13 +94,6 @@ static struct timer_list sclp_request_timer;
/* Timer for queued requests. */
static struct timer_list sclp_queue_timer;
-/* Internal state: is the driver initialized? */
-static volatile enum sclp_init_state_t {
- sclp_init_state_uninitialized,
- sclp_init_state_initializing,
- sclp_init_state_initialized
-} sclp_init_state = sclp_init_state_uninitialized;
-
/* Internal state: is a request active at the sclp? */
static volatile enum sclp_running_state_t {
sclp_running_state_idle,
@@ -147,31 +140,6 @@ static void __sclp_make_read_req(void);
static int sclp_init_mask(int calculate);
static int sclp_init(void);
-/* Perform service call. Return 0 on success, non-zero otherwise. */
-int
-sclp_service_call(sclp_cmdw_t command, void *sccb)
-{
- int cc = 4; /* Initialize for program check handling */
-
- asm volatile(
- "0: .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */
- "1: ipm %0\n"
- " srl %0,28\n"
- "2:\n"
- EX_TABLE(0b, 2b)
- EX_TABLE(1b, 2b)
- : "+&d" (cc) : "d" (command), "a" (__pa(sccb))
- : "cc", "memory");
- if (cc == 4)
- return -EINVAL;
- if (cc == 3)
- return -EIO;
- if (cc == 2)
- return -EBUSY;
- return 0;
-}
-
-
static void
__sclp_queue_read_req(void)
{
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index 7a10c56334bb..53b5d1b9761a 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -59,6 +59,7 @@
typedef unsigned int sclp_cmdw_t;
+#define SCLP_CMDW_READ_CPU_INFO 0x00010001
#define SCLP_CMDW_READ_EVENT_DATA 0x00770005
#define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005
#define SCLP_CMDW_WRITE_EVENT_MASK 0x00780005
@@ -102,6 +103,28 @@ struct init_sccb {
sccb_mask_t sclp_send_mask;
} __attribute__((packed));
+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 inline void sclp_fill_core_info(struct sclp_core_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;
+ memcpy(&info->core, page + sccb->offset_configured,
+ info->combined * sizeof(struct sclp_core_entry));
+}
+
#define SCLP_HAS_CHP_INFO (sclp.facilities & 0x8000000000000000ULL)
#define SCLP_HAS_CHP_RECONFIG (sclp.facilities & 0x2000000000000000ULL)
#define SCLP_HAS_CPU_INFO (sclp.facilities & 0x0800000000000000ULL)
@@ -181,19 +204,57 @@ void sclp_unregister(struct sclp_register *reg);
int sclp_remove_processed(struct sccb_header *sccb);
int sclp_deactivate(void);
int sclp_reactivate(void);
-int sclp_service_call(sclp_cmdw_t command, void *sccb);
int sclp_sync_request(sclp_cmdw_t command, void *sccb);
int sclp_sync_request_timeout(sclp_cmdw_t command, void *sccb, int timeout);
int sclp_sdias_init(void);
void sclp_sdias_exit(void);
+enum {
+ sclp_init_state_uninitialized,
+ sclp_init_state_initializing,
+ sclp_init_state_initialized
+};
+
+extern int sclp_init_state;
extern int sclp_console_pages;
extern int sclp_console_drop;
extern unsigned long sclp_console_full;
+extern char sclp_early_sccb[PAGE_SIZE];
+
+void sclp_early_wait_irq(void);
+int sclp_early_cmd(sclp_cmdw_t cmd, void *sccb);
+unsigned int sclp_early_con_check_linemode(struct init_sccb *sccb);
+int sclp_early_set_event_mask(struct init_sccb *sccb,
+ unsigned long receive_mask,
+ unsigned long send_mask);
+
/* useful inlines */
+/* Perform service call. Return 0 on success, non-zero otherwise. */
+static inline int sclp_service_call(sclp_cmdw_t command, void *sccb)
+{
+ int cc = 4; /* Initialize for program check handling */
+
+ asm volatile(
+ "0: .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */
+ "1: ipm %0\n"
+ " srl %0,28\n"
+ "2:\n"
+ EX_TABLE(0b, 2b)
+ EX_TABLE(1b, 2b)
+ : "+&d" (cc) : "d" (command), "a" ((unsigned long)sccb)
+ : "cc", "memory");
+ if (cc == 4)
+ return -EINVAL;
+ if (cc == 3)
+ return -EIO;
+ if (cc == 2)
+ return -EBUSY;
+ return 0;
+}
+
/* VM uses EBCDIC 037, LPAR+native(SE+HMC) use EBCDIC 500 */
/* translate single character from ASCII to EBCDIC */
static inline unsigned char
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index e3fc7539116b..b9c5522b8a68 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -80,33 +80,10 @@ out:
* 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_core_info(struct sclp_core_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;
- memcpy(&info->core, page + sccb->offset_configured,
- info->combined * sizeof(struct sclp_core_entry));
-}
-
-int sclp_get_core_info(struct sclp_core_info *info)
+int _sclp_get_core_info(struct sclp_core_info *info)
{
int rc;
struct read_cpu_info_sccb *sccb;
diff --git a/drivers/s390/char/sclp_ctl.c b/drivers/s390/char/sclp_ctl.c
index 554eaa1e347d..78a7e4f94721 100644
--- a/drivers/s390/char/sclp_ctl.c
+++ b/drivers/s390/char/sclp_ctl.c
@@ -10,7 +10,7 @@
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/gfp.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <asm/compat.h>
@@ -126,4 +126,4 @@ static struct miscdevice sclp_ctl_device = {
.name = "sclp",
.fops = &sclp_ctl_fops,
};
-module_misc_device(sclp_ctl_device);
+builtin_misc_device(sclp_ctl_device);
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c
index c71df0c7dedc..519ec1787117 100644
--- a/drivers/s390/char/sclp_early.c
+++ b/drivers/s390/char/sclp_early.c
@@ -55,46 +55,23 @@ struct read_info_sccb {
u8 _pad_128[4096 - 128]; /* 128-4095 */
} __packed __aligned(PAGE_SIZE);
-static char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE) __initdata;
static struct sclp_ipl_info sclp_ipl_info;
struct sclp_info sclp;
EXPORT_SYMBOL(sclp);
-static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
+static int __init sclp_early_read_info(struct read_info_sccb *sccb)
{
- int rc;
-
- __ctl_set_bit(0, 9);
- rc = sclp_service_call(cmd, sccb);
- if (rc)
- goto out;
- __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA |
- PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT);
- local_irq_disable();
-out:
- /* Contents of the sccb might have changed. */
- barrier();
- __ctl_clear_bit(0, 9);
- return rc;
-}
-
-static int __init sclp_read_info_early(struct read_info_sccb *sccb)
-{
- int rc, i;
+ int i;
sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
SCLP_CMDW_READ_SCP_INFO};
for (i = 0; i < ARRAY_SIZE(commands); i++) {
- do {
- memset(sccb, 0, sizeof(*sccb));
- sccb->header.length = sizeof(*sccb);
- sccb->header.function_code = 0x80;
- sccb->header.control_mask[2] = 0x80;
- rc = sclp_cmd_sync_early(commands[i], sccb);
- } while (rc == -EBUSY);
-
- if (rc)
+ memset(sccb, 0, sizeof(*sccb));
+ sccb->header.length = sizeof(*sccb);
+ sccb->header.function_code = 0x80;
+ sccb->header.control_mask[2] = 0x80;
+ if (sclp_early_cmd(commands[i], sccb))
break;
if (sccb->header.response_code == 0x10)
return 0;
@@ -104,12 +81,12 @@ static int __init sclp_read_info_early(struct read_info_sccb *sccb)
return -EIO;
}
-static void __init sclp_facilities_detect(struct read_info_sccb *sccb)
+static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb)
{
struct sclp_core_entry *cpue;
u16 boot_cpu_address, cpu;
- if (sclp_read_info_early(sccb))
+ if (sclp_early_read_info(sccb))
return;
sclp.facilities = sccb->facilities;
@@ -172,34 +149,43 @@ static void __init sclp_facilities_detect(struct read_info_sccb *sccb)
}
/*
- * This function will be called after sclp_facilities_detect(), which gets
- * called from early.c code. The sclp_facilities_detect() function retrieves
+ * This function will be called after sclp_early_facilities_detect(), which gets
+ * called from early.c code. The sclp_early_facilities_detect() function retrieves
* and saves the IPL information.
*/
-void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
+void __init sclp_early_get_ipl_info(struct sclp_ipl_info *info)
{
*info = sclp_ipl_info;
}
-static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb)
-{
- int rc;
+static struct sclp_core_info sclp_early_core_info __initdata;
+static int sclp_early_core_info_valid __initdata;
- do {
- rc = sclp_cmd_sync_early(cmd, sccb);
- } while (rc == -EBUSY);
+static void __init sclp_early_init_core_info(struct read_cpu_info_sccb *sccb)
+{
+ if (!SCLP_HAS_CPU_INFO)
+ return;
+ memset(sccb, 0, sizeof(*sccb));
+ sccb->header.length = sizeof(*sccb);
+ if (sclp_early_cmd(SCLP_CMDW_READ_CPU_INFO, sccb))
+ return;
+ if (sccb->header.response_code != 0x0010)
+ return;
+ sclp_fill_core_info(&sclp_early_core_info, sccb);
+ sclp_early_core_info_valid = 1;
+}
- if (rc)
- return -EIO;
- if (((struct sccb_header *) sccb)->response_code != 0x0020)
+int __init sclp_early_get_core_info(struct sclp_core_info *info)
+{
+ if (!sclp_early_core_info_valid)
return -EIO;
+ *info = sclp_early_core_info;
return 0;
}
-static void __init sccb_init_eq_size(struct sdias_sccb *sccb)
+static long __init sclp_early_hsa_size_init(struct sdias_sccb *sccb)
{
memset(sccb, 0, sizeof(*sccb));
-
sccb->hdr.length = sizeof(*sccb);
sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf);
sccb->evbuf.hdr.type = EVTYP_SDIAS;
@@ -207,76 +193,52 @@ static void __init sccb_init_eq_size(struct sdias_sccb *sccb)
sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP;
sccb->evbuf.event_id = 4712;
sccb->evbuf.dbs = 1;
-}
-
-static int __init sclp_set_event_mask(struct init_sccb *sccb,
- unsigned long receive_mask,
- unsigned long send_mask)
-{
- memset(sccb, 0, sizeof(*sccb));
- sccb->header.length = sizeof(*sccb);
- sccb->mask_length = sizeof(sccb_mask_t);
- sccb->receive_mask = receive_mask;
- sccb->send_mask = send_mask;
- return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb);
-}
-
-static long __init sclp_hsa_size_init(struct sdias_sccb *sccb)
-{
- sccb_init_eq_size(sccb);
- if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb))
+ if (sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_DATA, sccb))
+ return -EIO;
+ if (sccb->hdr.response_code != 0x20)
return -EIO;
if (sccb->evbuf.blk_cnt == 0)
return 0;
return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE;
}
-static long __init sclp_hsa_copy_wait(struct sccb_header *sccb)
+static long __init sclp_early_hsa_copy_wait(struct sdias_sccb *sccb)
{
memset(sccb, 0, PAGE_SIZE);
- sccb->length = PAGE_SIZE;
- if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb))
+ sccb->hdr.length = PAGE_SIZE;
+ if (sclp_early_cmd(SCLP_CMDW_READ_EVENT_DATA, sccb))
+ return -EIO;
+ if ((sccb->hdr.response_code != 0x20) && (sccb->hdr.response_code != 0x220))
return -EIO;
- if (((struct sdias_sccb *) sccb)->evbuf.blk_cnt == 0)
+ if (sccb->evbuf.blk_cnt == 0)
return 0;
- return (((struct sdias_sccb *) sccb)->evbuf.blk_cnt - 1) * PAGE_SIZE;
+ return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE;
}
-static void __init sclp_hsa_size_detect(void *sccb)
+static void __init sclp_early_hsa_size_detect(void *sccb)
{
- long size;
+ unsigned long flags;
+ long size = -EIO;
- /* First try synchronous interface (LPAR) */
- if (sclp_set_event_mask(sccb, 0, 0x40000010))
- return;
- size = sclp_hsa_size_init(sccb);
- if (size < 0)
- return;
- if (size != 0)
+ raw_local_irq_save(flags);
+ if (sclp_early_set_event_mask(sccb, EVTYP_SDIAS_MASK, EVTYP_SDIAS_MASK))
goto out;
- /* Then try asynchronous interface (z/VM) */
- if (sclp_set_event_mask(sccb, 0x00000010, 0x40000010))
- return;
- size = sclp_hsa_size_init(sccb);
- if (size < 0)
- return;
- size = sclp_hsa_copy_wait(sccb);
- if (size < 0)
- return;
+ size = sclp_early_hsa_size_init(sccb);
+ /* First check for synchronous response (LPAR) */
+ if (size)
+ goto out_mask;
+ if (!(S390_lowcore.ext_params & 1))
+ sclp_early_wait_irq();
+ size = sclp_early_hsa_copy_wait(sccb);
+out_mask:
+ sclp_early_set_event_mask(sccb, 0, 0);
out:
- sclp.hsa_size = size;
-}
-
-static unsigned int __init sclp_con_check_linemode(struct init_sccb *sccb)
-{
- if (!(sccb->sclp_send_mask & EVTYP_OPCMD_MASK))
- return 0;
- if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)))
- return 0;
- return 1;
+ raw_local_irq_restore(flags);
+ if (size > 0)
+ sclp.hsa_size = size;
}
-static void __init sclp_console_detect(struct init_sccb *sccb)
+static void __init sclp_early_console_detect(struct init_sccb *sccb)
{
if (sccb->header.response_code != 0x20)
return;
@@ -284,20 +246,22 @@ static void __init sclp_console_detect(struct init_sccb *sccb)
if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK)
sclp.has_vt220 = 1;
- if (sclp_con_check_linemode(sccb))
+ if (sclp_early_con_check_linemode(sccb))
sclp.has_linemode = 1;
}
void __init sclp_early_detect(void)
{
- void *sccb = &sccb_early;
+ void *sccb = &sclp_early_sccb;
- sclp_facilities_detect(sccb);
- sclp_hsa_size_detect(sccb);
+ sclp_early_facilities_detect(sccb);
+ sclp_early_init_core_info(sccb);
+ sclp_early_hsa_size_detect(sccb);
- /* Turn off SCLP event notifications. Also save remote masks in the
+ /*
+ * Turn off SCLP event notifications. Also save remote masks in the
* sccb. These are sufficient to detect sclp console capabilities.
*/
- sclp_set_event_mask(sccb, 0, 0);
- sclp_console_detect(sccb);
+ sclp_early_set_event_mask(sccb, 0, 0);
+ sclp_early_console_detect(sccb);
}
diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c
new file mode 100644
index 000000000000..5029cc87e80f
--- /dev/null
+++ b/drivers/s390/char/sclp_early_core.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright IBM Corp. 2015
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <asm/processor.h>
+#include <asm/lowcore.h>
+#include <asm/ebcdic.h>
+#include <asm/irq.h>
+#include "sclp.h"
+#include "sclp_rw.h"
+
+char sclp_early_sccb[PAGE_SIZE] __aligned(PAGE_SIZE) __section(data);
+int sclp_init_state __section(data) = sclp_init_state_uninitialized;
+
+void sclp_early_wait_irq(void)
+{
+ unsigned long psw_mask, addr;
+ psw_t psw_ext_save, psw_wait;
+ union ctlreg0 cr0, cr0_new;
+
+ __ctl_store(cr0.val, 0, 0);
+ cr0_new.val = cr0.val & ~CR0_IRQ_SUBCLASS_MASK;
+ cr0_new.lap = 0;
+ cr0_new.sssm = 1;
+ __ctl_load(cr0_new.val, 0, 0);
+
+ psw_ext_save = S390_lowcore.external_new_psw;
+ psw_mask = __extract_psw();
+ S390_lowcore.external_new_psw.mask = psw_mask;
+ psw_wait.mask = psw_mask | PSW_MASK_EXT | PSW_MASK_WAIT;
+ S390_lowcore.ext_int_code = 0;
+
+ do {
+ asm volatile(
+ " larl %[addr],0f\n"
+ " stg %[addr],%[psw_wait_addr]\n"
+ " stg %[addr],%[psw_ext_addr]\n"
+ " lpswe %[psw_wait]\n"
+ "0:\n"
+ : [addr] "=&d" (addr),
+ [psw_wait_addr] "=Q" (psw_wait.addr),
+ [psw_ext_addr] "=Q" (S390_lowcore.external_new_psw.addr)
+ : [psw_wait] "Q" (psw_wait)
+ : "cc", "memory");
+ } while (S390_lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG);
+
+ S390_lowcore.external_new_psw = psw_ext_save;
+ __ctl_load(cr0.val, 0, 0);
+}
+
+int sclp_early_cmd(sclp_cmdw_t cmd, void *sccb)
+{
+ unsigned long flags;
+ int rc;
+
+ raw_local_irq_save(flags);
+ rc = sclp_service_call(cmd, sccb);
+ if (rc)
+ goto out;
+ sclp_early_wait_irq();
+out:
+ raw_local_irq_restore(flags);
+ return rc;
+}
+
+struct write_sccb {
+ struct sccb_header header;
+ struct msg_buf msg;
+} __packed;
+
+/* Output multi-line text using SCLP Message interface. */
+static void sclp_early_print_lm(const char *str, unsigned int len)
+{
+ unsigned char *ptr, *end, ch;
+ unsigned int count, offset;
+ struct write_sccb *sccb;
+ struct msg_buf *msg;
+ struct mdb *mdb;
+ struct mto *mto;
+ struct go *go;
+
+ sccb = (struct write_sccb *) &sclp_early_sccb;
+ end = (unsigned char *) sccb + sizeof(sclp_early_sccb) - 1;
+ memset(sccb, 0, sizeof(*sccb));
+ ptr = (unsigned char *) &sccb->msg.mdb.mto;
+ offset = 0;
+ do {
+ for (count = sizeof(*mto); offset < len; count++) {
+ ch = str[offset++];
+ if ((ch == 0x0a) || (ptr + count > end))
+ break;
+ ptr[count] = _ascebc[ch];
+ }
+ mto = (struct mto *) ptr;
+ memset(mto, 0, sizeof(*mto));
+ mto->length = count;
+ mto->type = 4;
+ mto->line_type_flags = LNTPFLGS_ENDTEXT;
+ ptr += count;
+ } while ((offset < len) && (ptr + sizeof(*mto) <= end));
+ len = ptr - (unsigned char *) sccb;
+ sccb->header.length = len - offsetof(struct write_sccb, header);
+ msg = &sccb->msg;
+ msg->header.type = EVTYP_MSG;
+ msg->header.length = len - offsetof(struct write_sccb, msg.header);
+ mdb = &msg->mdb;
+ mdb->header.type = 1;
+ mdb->header.tag = 0xD4C4C240;
+ mdb->header.revision_code = 1;
+ mdb->header.length = len - offsetof(struct write_sccb, msg.mdb.header);
+ go = &mdb->go;
+ go->length = sizeof(*go);
+ go->type = 1;
+ sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_DATA, sccb);
+}
+
+struct vt220_sccb {
+ struct sccb_header header;
+ struct {
+ struct evbuf_header header;
+ char data[];
+ } msg;
+} __packed;
+
+/* Output multi-line text using SCLP VT220 interface. */
+static void sclp_early_print_vt220(const char *str, unsigned int len)
+{
+ struct vt220_sccb *sccb;
+
+ sccb = (struct vt220_sccb *) &sclp_early_sccb;
+ if (sizeof(*sccb) + len >= sizeof(sclp_early_sccb))
+ len = sizeof(sclp_early_sccb) - sizeof(*sccb);
+ memset(sccb, 0, sizeof(*sccb));
+ memcpy(&sccb->msg.data, str, len);
+ sccb->header.length = sizeof(*sccb) + len;
+ sccb->msg.header.length = sizeof(sccb->msg) + len;
+ sccb->msg.header.type = EVTYP_VT220MSG;
+ sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_DATA, sccb);
+}
+
+int sclp_early_set_event_mask(struct init_sccb *sccb,
+ unsigned long receive_mask,
+ unsigned long send_mask)
+{
+ memset(sccb, 0, sizeof(*sccb));
+ sccb->header.length = sizeof(*sccb);
+ sccb->mask_length = sizeof(sccb_mask_t);
+ sccb->receive_mask = receive_mask;
+ sccb->send_mask = send_mask;
+ if (sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_MASK, sccb))
+ return -EIO;
+ if (sccb->header.response_code != 0x20)
+ return -EIO;
+ return 0;
+}
+
+unsigned int sclp_early_con_check_linemode(struct init_sccb *sccb)
+{
+ if (!(sccb->sclp_send_mask & EVTYP_OPCMD_MASK))
+ return 0;
+ if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)))
+ return 0;
+ return 1;
+}
+
+static int sclp_early_setup(int disable, int *have_linemode, int *have_vt220)
+{
+ unsigned long receive_mask, send_mask;
+ struct init_sccb *sccb;
+ int rc;
+
+ *have_linemode = *have_vt220 = 0;
+ sccb = (struct init_sccb *) &sclp_early_sccb;
+ receive_mask = disable ? 0 : EVTYP_OPCMD_MASK;
+ send_mask = disable ? 0 : EVTYP_VT220MSG_MASK | EVTYP_MSG_MASK;
+ rc = sclp_early_set_event_mask(sccb, receive_mask, send_mask);
+ if (rc)
+ return rc;
+ *have_linemode = sclp_early_con_check_linemode(sccb);
+ *have_vt220 = sccb->send_mask & EVTYP_VT220MSG_MASK;
+ return rc;
+}
+
+/*
+ * Output one or more lines of text on the SCLP console (VT220 and /
+ * or line-mode).
+ */
+void __sclp_early_printk(const char *str, unsigned int len)
+{
+ int have_linemode, have_vt220;
+
+ if (sclp_init_state != sclp_init_state_uninitialized)
+ return;
+ if (sclp_early_setup(0, &have_linemode, &have_vt220) != 0)
+ return;
+ if (have_linemode)
+ sclp_early_print_lm(str, len);
+ if (have_vt220)
+ sclp_early_print_vt220(str, len);
+ sclp_early_setup(1, &have_linemode, &have_vt220);
+}
+
+void sclp_early_printk(const char *str)
+{
+ __sclp_early_printk(str, strlen(str));
+}
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 475e470d9768..e4958511168a 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -6,7 +6,6 @@
* Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
*/
-#include <linux/module.h>
#include <linux/types.h>
#include <linux/cpumask.h>
#include <linux/smp.h>
@@ -80,5 +79,4 @@ static int __init sclp_quiesce_init(void)
{
return sclp_register(&sclp_quiesce_event);
}
-
-module_init(sclp_quiesce_init);
+device_initcall(sclp_quiesce_init);
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index 6010cd347a08..91b26df5227d 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -13,7 +13,7 @@
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/ctype.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "sclp.h"
#include "sclp_rw.h"
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 3c6e174e19b6..236b736ae136 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -7,7 +7,6 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -16,7 +15,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/gfp.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "ctrlchar.h"
#include "sclp.h"
@@ -573,4 +572,4 @@ sclp_tty_init(void)
sclp_tty_driver = driver;
return 0;
}
-module_init(sclp_tty_init);
+device_initcall(sclp_tty_init);
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 68d6ee7ae504..095481d32236 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -26,7 +26,7 @@
#include <linux/reboot.h>
#include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "sclp.h"
#include "ctrlchar.h"
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 77f9b9c2f701..46ac1164f242 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -18,7 +18,7 @@
#include <linux/mtio.h>
#include <linux/compat.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#define TAPE_DBF_AREA tape_core_dbf
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 272cb6cd1b2a..e5ebe2fbee23 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -24,7 +24,7 @@
#include <asm/ccwdev.h>
#include <asm/cio.h>
#include <asm/ebcdic.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "raw3270.h"
#include "tty3270.h"
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 2a67b496a9e2..65f5a794f26d 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -21,7 +21,7 @@
#include <asm/compat.h>
#include <asm/cpcmd.h>
#include <asm/debug.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "vmcp.h"
static debug_info_t *vmcp_debug;
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index e883063c7258..57974a1e0e03 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -21,7 +21,7 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/atomic.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/cpcmd.h>
#include <asm/debug.h>
#include <asm/ebcdic.h>
@@ -870,7 +870,7 @@ static int __init vmlogrdr_init(void)
goto cleanup;
for (i=0; i < MAXMINOR; ++i ) {
- sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL);
+ sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!sys_ser[i].buffer) {
rc = -ENOMEM;
break;
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index ff18f373af9a..04aceb694d51 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -15,7 +15,7 @@
#include <linux/slab.h>
#include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/cio.h>
#include <asm/ccwdev.h>
#include <asm/debug.h>
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 16992e2a40ad..aaed778f67c4 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -7,6 +7,7 @@
*
* Copyright IBM Corp. 2003, 2008
* Author(s): Michael Holzheu
+ * License: GPL
*/
#define KMSG_COMPONENT "zdump"
@@ -14,16 +15,14 @@
#include <linux/init.h>
#include <linux/slab.h>
-#include <linux/miscdevice.h>
#include <linux/debugfs.h>
-#include <linux/module.h>
#include <linux/memblock.h>
#include <asm/asm-offsets.h>
#include <asm/ipl.h>
#include <asm/sclp.h>
#include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/debug.h>
#include <asm/processor.h>
#include <asm/irqflags.h>
@@ -273,7 +272,7 @@ static int __init zcore_reipl_init(void)
rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE);
else
rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE);
- if (rc || csum_partial(ipl_block, ipl_block->hdr.len, 0) !=
+ if (rc || (__force u32)csum_partial(ipl_block, ipl_block->hdr.len, 0) !=
ipib_info.checksum) {
TRACE("Checksum does not match\n");
free_page((unsigned long) ipl_block);
@@ -320,7 +319,7 @@ static int __init zcore_init(void)
goto fail;
}
- pr_alert("DETECTED 'S390X (64 bit) OS'\n");
+ pr_alert("The dump process started for a 64-bit operating system\n");
rc = init_cpu_info();
if (rc)
goto fail;
@@ -364,22 +363,4 @@ fail:
diag308(DIAG308_REL_HSA, NULL);
return rc;
}
-
-static void __exit zcore_exit(void)
-{
- debug_unregister(zcore_dbf);
- sclp_sdias_exit();
- free_page((unsigned long) ipl_block);
- debugfs_remove(zcore_hsa_file);
- debugfs_remove(zcore_reipl_file);
- debugfs_remove(zcore_memmap_file);
- debugfs_remove(zcore_dir);
- diag308(DIAG308_REL_HSA, NULL);
-}
-
-MODULE_AUTHOR("Copyright IBM Corp. 2003,2008");
-MODULE_DESCRIPTION("zcore module for zfcpdump support");
-MODULE_LICENSE("GPL");
-
subsys_initcall(zcore_init);
-module_exit(zcore_exit);