Commit 9c65ed96 authored by Peter Oberparleiter's avatar Peter Oberparleiter Committed by Linus Torvalds

[PATCH] s390: sclp driver changes

sclp driver changes:
 - Add reboot notifier to reset the sclp send/receive masks on shutdown.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 015af483
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/reboot.h>
#include <asm/s390_ext.h> #include <asm/s390_ext.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -60,6 +61,7 @@ static volatile unsigned long sclp_status = 0; ...@@ -60,6 +61,7 @@ static volatile unsigned long sclp_status = 0;
#define SCLP_INIT 0 #define SCLP_INIT 0
#define SCLP_RUNNING 1 #define SCLP_RUNNING 1
#define SCLP_READING 2 #define SCLP_READING 2
#define SCLP_SHUTDOWN 3
#define SCLP_INIT_POLL_INTERVAL 1 #define SCLP_INIT_POLL_INTERVAL 1
#define SCLP_BUSY_POLL_INTERVAL 1 #define SCLP_BUSY_POLL_INTERVAL 1
...@@ -606,11 +608,13 @@ sclp_init_mask(void) ...@@ -606,11 +608,13 @@ sclp_init_mask(void)
sccb->mask_length = sizeof(sccb_mask_t); sccb->mask_length = sizeof(sccb_mask_t);
/* copy in the sccb mask of the registered event types */ /* copy in the sccb mask of the registered event types */
spin_lock_irqsave(&sclp_lock, flags); spin_lock_irqsave(&sclp_lock, flags);
if (!test_bit(SCLP_SHUTDOWN, &sclp_status)) {
list_for_each(l, &sclp_reg_list) { list_for_each(l, &sclp_reg_list) {
t = list_entry(l, struct sclp_register, list); t = list_entry(l, struct sclp_register, list);
sccb->receive_mask |= t->receive_mask; sccb->receive_mask |= t->receive_mask;
sccb->send_mask |= t->send_mask; sccb->send_mask |= t->send_mask;
} }
}
sccb->sclp_receive_mask = 0; sccb->sclp_receive_mask = 0;
sccb->sclp_send_mask = 0; sccb->sclp_send_mask = 0;
if (test_bit(SCLP_INIT, &sclp_status)) { if (test_bit(SCLP_INIT, &sclp_status)) {
...@@ -647,9 +651,10 @@ sclp_init_mask(void) ...@@ -647,9 +651,10 @@ sclp_init_mask(void)
/* WRITEMASK failed - we cannot rely on receiving a state /* WRITEMASK failed - we cannot rely on receiving a state
change event, so initially, polling is the only alternative change event, so initially, polling is the only alternative
for us to ever become operational. */ for us to ever become operational. */
if (!timer_pending(&retry_timer) || if (!test_bit(SCLP_SHUTDOWN, &sclp_status) &&
(!timer_pending(&retry_timer) ||
!mod_timer(&retry_timer, !mod_timer(&retry_timer,
jiffies + SCLP_INIT_POLL_INTERVAL*HZ)) { jiffies + SCLP_INIT_POLL_INTERVAL*HZ))) {
retry_timer.function = sclp_init_mask_retry; retry_timer.function = sclp_init_mask_retry;
retry_timer.data = 0; retry_timer.data = 0;
retry_timer.expires = jiffies + retry_timer.expires = jiffies +
...@@ -671,6 +676,26 @@ sclp_init_mask_retry(unsigned long data) ...@@ -671,6 +676,26 @@ sclp_init_mask_retry(unsigned long data)
sclp_init_mask(); sclp_init_mask();
} }
/* Reboot event handler - reset send and receive mask to prevent pending SCLP
* events from interfering with rebooted system. */
static int
sclp_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
{
unsigned long flags;
/* Note: need spinlock to maintain atomicity when accessing global
* variables. */
spin_lock_irqsave(&sclp_lock, flags);
set_bit(SCLP_SHUTDOWN, &sclp_status);
spin_unlock_irqrestore(&sclp_lock, flags);
sclp_init_mask();
return NOTIFY_DONE;
}
static struct notifier_block sclp_reboot_notifier = {
.notifier_call = sclp_reboot_event
};
/* /*
* sclp setup function. Called early (no kmalloc!) from sclp_console_init(). * sclp setup function. Called early (no kmalloc!) from sclp_console_init().
*/ */
...@@ -691,6 +716,10 @@ sclp_init(void) ...@@ -691,6 +716,10 @@ sclp_init(void)
list_add(&sclp_state_change_event.list, &sclp_reg_list); list_add(&sclp_state_change_event.list, &sclp_reg_list);
list_add(&sclp_quiesce_event.list, &sclp_reg_list); list_add(&sclp_quiesce_event.list, &sclp_reg_list);
rc = register_reboot_notifier(&sclp_reboot_notifier);
if (rc)
return rc;
/* /*
* request the 0x2401 external interrupt * request the 0x2401 external interrupt
* The sclp driver is initialized early (before kmalloc works). We * The sclp driver is initialized early (before kmalloc works). We
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment