summaryrefslogtreecommitdiff
path: root/drivers/s390/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/monreader.c1
-rw-r--r--drivers/s390/char/sclp_async.c47
-rw-r--r--drivers/s390/char/sclp_quiesce.c48
3 files changed, 57 insertions, 39 deletions
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 89ece1c235aa..66e21dd23154 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -357,6 +357,7 @@ static int mon_close(struct inode *inode, struct file *filp)
atomic_set(&monpriv->msglim_count, 0);
monpriv->write_index = 0;
monpriv->read_index = 0;
+ dev_set_drvdata(monreader_device, NULL);
for (i = 0; i < MON_MSGLIM; i++)
kfree(monpriv->msg_array[i]);
diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c
index a4f68e5b9c96..b44462a6c6d3 100644
--- a/drivers/s390/char/sclp_async.c
+++ b/drivers/s390/char/sclp_async.c
@@ -26,7 +26,6 @@ static struct sclp_async_sccb *sccb;
static int sclp_async_send_wait(char *message);
static struct ctl_table_header *callhome_sysctl_header;
static DEFINE_SPINLOCK(sclp_async_lock);
-static char nodename[64];
#define SCLP_NORMAL_WRITE 0x00
struct async_evbuf {
@@ -52,9 +51,10 @@ static struct sclp_register sclp_async_register = {
static int call_home_on_panic(struct notifier_block *self,
unsigned long event, void *data)
{
- strncat(data, nodename, strlen(nodename));
- sclp_async_send_wait(data);
- return NOTIFY_DONE;
+ strncat(data, init_utsname()->nodename,
+ sizeof(init_utsname()->nodename));
+ sclp_async_send_wait(data);
+ return NOTIFY_DONE;
}
static struct notifier_block call_home_panic_nb = {
@@ -68,15 +68,14 @@ static int proc_handler_callhome(struct ctl_table *ctl, int write,
{
unsigned long val;
int len, rc;
- char buf[2];
+ char buf[3];
- if (!*count | (*ppos && !write)) {
+ if (!*count || (*ppos && !write)) {
*count = 0;
return 0;
}
if (!write) {
- len = sprintf(buf, "%d\n", callhome_enabled);
- buf[len] = '\0';
+ len = snprintf(buf, sizeof(buf), "%d\n", callhome_enabled);
rc = copy_to_user(buffer, buf, sizeof(buf));
if (rc != 0)
return -EFAULT;
@@ -171,39 +170,29 @@ static int __init sclp_async_init(void)
rc = sclp_register(&sclp_async_register);
if (rc)
return rc;
- callhome_sysctl_header = register_sysctl_table(kern_dir_table);
- if (!callhome_sysctl_header) {
- rc = -ENOMEM;
- goto out_sclp;
- }
- if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK)) {
- rc = -EOPNOTSUPP;
+ rc = -EOPNOTSUPP;
+ if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK))
goto out_sclp;
- }
rc = -ENOMEM;
+ callhome_sysctl_header = register_sysctl_table(kern_dir_table);
+ if (!callhome_sysctl_header)
+ goto out_sclp;
request = kzalloc(sizeof(struct sclp_req), GFP_KERNEL);
- if (!request)
- goto out_sys;
sccb = (struct sclp_async_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
- if (!sccb)
+ if (!request || !sccb)
goto out_mem;
- rc = atomic_notifier_chain_register(&panic_notifier_list,
- &call_home_panic_nb);
- if (rc)
- goto out_mem;
-
- strncpy(nodename, init_utsname()->nodename, 64);
- return 0;
-
+ rc = atomic_notifier_chain_register(&panic_notifier_list,
+ &call_home_panic_nb);
+ if (!rc)
+ goto out;
out_mem:
kfree(request);
free_page((unsigned long) sccb);
-out_sys:
unregister_sysctl_table(callhome_sysctl_header);
out_sclp:
sclp_unregister(&sclp_async_register);
+out:
return rc;
-
}
module_init(sclp_async_init);
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 84c191c1cd62..05909a7df8b3 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -20,9 +20,12 @@
#include "sclp.h"
+static void (*old_machine_restart)(char *);
+static void (*old_machine_halt)(void);
+static void (*old_machine_power_off)(void);
+
/* Shutdown handler. Signal completion of shutdown by loading special PSW. */
-static void
-do_machine_quiesce(void)
+static void do_machine_quiesce(void)
{
psw_t quiesce_psw;
@@ -33,23 +36,48 @@ do_machine_quiesce(void)
}
/* Handler for quiesce event. Start shutdown procedure. */
-static void
-sclp_quiesce_handler(struct evbuf_header *evbuf)
+static void sclp_quiesce_handler(struct evbuf_header *evbuf)
{
- _machine_restart = (void *) do_machine_quiesce;
- _machine_halt = do_machine_quiesce;
- _machine_power_off = do_machine_quiesce;
+ if (_machine_restart != (void *) do_machine_quiesce) {
+ old_machine_restart = _machine_restart;
+ old_machine_halt = _machine_halt;
+ old_machine_power_off = _machine_power_off;
+ _machine_restart = (void *) do_machine_quiesce;
+ _machine_halt = do_machine_quiesce;
+ _machine_power_off = do_machine_quiesce;
+ }
ctrl_alt_del();
}
+/* Undo machine restart/halt/power_off modification on resume */
+static void sclp_quiesce_pm_event(struct sclp_register *reg,
+ enum sclp_pm_event sclp_pm_event)
+{
+ switch (sclp_pm_event) {
+ case SCLP_PM_EVENT_RESTORE:
+ if (old_machine_restart) {
+ _machine_restart = old_machine_restart;
+ _machine_halt = old_machine_halt;
+ _machine_power_off = old_machine_power_off;
+ old_machine_restart = NULL;
+ old_machine_halt = NULL;
+ old_machine_power_off = NULL;
+ }
+ break;
+ case SCLP_PM_EVENT_FREEZE:
+ case SCLP_PM_EVENT_THAW:
+ break;
+ }
+}
+
static struct sclp_register sclp_quiesce_event = {
.receive_mask = EVTYP_SIGQUIESCE_MASK,
- .receiver_fn = sclp_quiesce_handler
+ .receiver_fn = sclp_quiesce_handler,
+ .pm_event_fn = sclp_quiesce_pm_event
};
/* Initialize quiesce driver. */
-static int __init
-sclp_quiesce_init(void)
+static int __init sclp_quiesce_init(void)
{
return sclp_register(&sclp_quiesce_event);
}