mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 04:06:22 +00:00
[S390] iucv: establish reboot notifier
To guarantee a proper cleanup, patch adds a reboot notifier to the iucv base code, which disables iucv interrupts, shuts down established iucv pathes, and removes iucv declarations for z/VM. Checks have to be added to the iucv-API functions, whether iucv-buffers removed at reboot time are still declared. Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
62b7494209
commit
6c005961c1
1 changed files with 87 additions and 2 deletions
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* IUCV base infrastructure.
|
* IUCV base infrastructure.
|
||||||
*
|
*
|
||||||
* Copyright 2001, 2006 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
* Copyright IBM Corp. 2001, 2009
|
||||||
|
*
|
||||||
* Author(s):
|
* Author(s):
|
||||||
* Original source:
|
* Original source:
|
||||||
* Alan Altmark (Alan_Altmark@us.ibm.com) Sept. 2000
|
* Alan Altmark (Alan_Altmark@us.ibm.com) Sept. 2000
|
||||||
|
@ -45,6 +46,7 @@
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
#include <net/iucv/iucv.h>
|
#include <net/iucv/iucv.h>
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/ebcdic.h>
|
#include <asm/ebcdic.h>
|
||||||
|
@ -758,6 +760,28 @@ void iucv_unregister(struct iucv_handler *handler, int smp)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iucv_unregister);
|
EXPORT_SYMBOL(iucv_unregister);
|
||||||
|
|
||||||
|
static int iucv_reboot_event(struct notifier_block *this,
|
||||||
|
unsigned long event, void *ptr)
|
||||||
|
{
|
||||||
|
int i, rc;
|
||||||
|
|
||||||
|
get_online_cpus();
|
||||||
|
on_each_cpu(iucv_block_cpu, NULL, 1);
|
||||||
|
preempt_disable();
|
||||||
|
for (i = 0; i < iucv_max_pathid; i++) {
|
||||||
|
if (iucv_path_table[i])
|
||||||
|
rc = iucv_sever_pathid(i, NULL);
|
||||||
|
}
|
||||||
|
preempt_enable();
|
||||||
|
put_online_cpus();
|
||||||
|
iucv_disable();
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct notifier_block iucv_reboot_notifier = {
|
||||||
|
.notifier_call = iucv_reboot_event,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iucv_path_accept
|
* iucv_path_accept
|
||||||
* @path: address of iucv path structure
|
* @path: address of iucv path structure
|
||||||
|
@ -777,6 +801,10 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
|
if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
/* Prepare parameter block. */
|
/* Prepare parameter block. */
|
||||||
parm = iucv_param[smp_processor_id()];
|
parm = iucv_param[smp_processor_id()];
|
||||||
memset(parm, 0, sizeof(union iucv_param));
|
memset(parm, 0, sizeof(union iucv_param));
|
||||||
|
@ -792,6 +820,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
|
||||||
path->msglim = parm->ctrl.ipmsglim;
|
path->msglim = parm->ctrl.ipmsglim;
|
||||||
path->flags = parm->ctrl.ipflags1;
|
path->flags = parm->ctrl.ipflags1;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -821,6 +850,10 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
|
||||||
|
|
||||||
spin_lock_bh(&iucv_table_lock);
|
spin_lock_bh(&iucv_table_lock);
|
||||||
iucv_cleanup_queue();
|
iucv_cleanup_queue();
|
||||||
|
if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
parm = iucv_param[smp_processor_id()];
|
parm = iucv_param[smp_processor_id()];
|
||||||
memset(parm, 0, sizeof(union iucv_param));
|
memset(parm, 0, sizeof(union iucv_param));
|
||||||
parm->ctrl.ipmsglim = path->msglim;
|
parm->ctrl.ipmsglim = path->msglim;
|
||||||
|
@ -855,6 +888,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
spin_unlock_bh(&iucv_table_lock);
|
spin_unlock_bh(&iucv_table_lock);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -876,12 +910,17 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16])
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
|
if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
parm = iucv_param[smp_processor_id()];
|
parm = iucv_param[smp_processor_id()];
|
||||||
memset(parm, 0, sizeof(union iucv_param));
|
memset(parm, 0, sizeof(union iucv_param));
|
||||||
if (userdata)
|
if (userdata)
|
||||||
memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
|
memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
|
||||||
parm->ctrl.ippathid = path->pathid;
|
parm->ctrl.ippathid = path->pathid;
|
||||||
rc = iucv_call_b2f0(IUCV_QUIESCE, parm);
|
rc = iucv_call_b2f0(IUCV_QUIESCE, parm);
|
||||||
|
out:
|
||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -903,12 +942,17 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16])
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
|
if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
parm = iucv_param[smp_processor_id()];
|
parm = iucv_param[smp_processor_id()];
|
||||||
memset(parm, 0, sizeof(union iucv_param));
|
memset(parm, 0, sizeof(union iucv_param));
|
||||||
if (userdata)
|
if (userdata)
|
||||||
memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
|
memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
|
||||||
parm->ctrl.ippathid = path->pathid;
|
parm->ctrl.ippathid = path->pathid;
|
||||||
rc = iucv_call_b2f0(IUCV_RESUME, parm);
|
rc = iucv_call_b2f0(IUCV_RESUME, parm);
|
||||||
|
out:
|
||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -927,6 +971,10 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
|
if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (iucv_active_cpu != smp_processor_id())
|
if (iucv_active_cpu != smp_processor_id())
|
||||||
spin_lock_bh(&iucv_table_lock);
|
spin_lock_bh(&iucv_table_lock);
|
||||||
rc = iucv_sever_pathid(path->pathid, userdata);
|
rc = iucv_sever_pathid(path->pathid, userdata);
|
||||||
|
@ -934,6 +982,7 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
|
||||||
list_del_init(&path->list);
|
list_del_init(&path->list);
|
||||||
if (iucv_active_cpu != smp_processor_id())
|
if (iucv_active_cpu != smp_processor_id())
|
||||||
spin_unlock_bh(&iucv_table_lock);
|
spin_unlock_bh(&iucv_table_lock);
|
||||||
|
out:
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -956,6 +1005,10 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
|
if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
parm = iucv_param[smp_processor_id()];
|
parm = iucv_param[smp_processor_id()];
|
||||||
memset(parm, 0, sizeof(union iucv_param));
|
memset(parm, 0, sizeof(union iucv_param));
|
||||||
parm->purge.ippathid = path->pathid;
|
parm->purge.ippathid = path->pathid;
|
||||||
|
@ -967,6 +1020,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
|
||||||
msg->audit = (*(u32 *) &parm->purge.ipaudit) >> 8;
|
msg->audit = (*(u32 *) &parm->purge.ipaudit) >> 8;
|
||||||
msg->tag = parm->purge.ipmsgtag;
|
msg->tag = parm->purge.ipmsgtag;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1043,6 +1097,10 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
|
||||||
if (msg->flags & IUCV_IPRMDATA)
|
if (msg->flags & IUCV_IPRMDATA)
|
||||||
return iucv_message_receive_iprmdata(path, msg, flags,
|
return iucv_message_receive_iprmdata(path, msg, flags,
|
||||||
buffer, size, residual);
|
buffer, size, residual);
|
||||||
|
if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
parm = iucv_param[smp_processor_id()];
|
parm = iucv_param[smp_processor_id()];
|
||||||
memset(parm, 0, sizeof(union iucv_param));
|
memset(parm, 0, sizeof(union iucv_param));
|
||||||
parm->db.ipbfadr1 = (u32)(addr_t) buffer;
|
parm->db.ipbfadr1 = (u32)(addr_t) buffer;
|
||||||
|
@ -1058,6 +1116,7 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
|
||||||
if (residual)
|
if (residual)
|
||||||
*residual = parm->db.ipbfln1f;
|
*residual = parm->db.ipbfln1f;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__iucv_message_receive);
|
EXPORT_SYMBOL(__iucv_message_receive);
|
||||||
|
@ -1111,6 +1170,10 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
|
if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
parm = iucv_param[smp_processor_id()];
|
parm = iucv_param[smp_processor_id()];
|
||||||
memset(parm, 0, sizeof(union iucv_param));
|
memset(parm, 0, sizeof(union iucv_param));
|
||||||
parm->db.ippathid = path->pathid;
|
parm->db.ippathid = path->pathid;
|
||||||
|
@ -1118,6 +1181,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
|
||||||
parm->db.iptrgcls = msg->class;
|
parm->db.iptrgcls = msg->class;
|
||||||
parm->db.ipflags1 = (IUCV_IPTRGCLS | IUCV_IPFGMID | IUCV_IPFGPID);
|
parm->db.ipflags1 = (IUCV_IPTRGCLS | IUCV_IPFGMID | IUCV_IPFGPID);
|
||||||
rc = iucv_call_b2f0(IUCV_REJECT, parm);
|
rc = iucv_call_b2f0(IUCV_REJECT, parm);
|
||||||
|
out:
|
||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1145,6 +1209,10 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
|
if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
parm = iucv_param[smp_processor_id()];
|
parm = iucv_param[smp_processor_id()];
|
||||||
memset(parm, 0, sizeof(union iucv_param));
|
memset(parm, 0, sizeof(union iucv_param));
|
||||||
if (flags & IUCV_IPRMDATA) {
|
if (flags & IUCV_IPRMDATA) {
|
||||||
|
@ -1162,6 +1230,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
|
||||||
parm->db.iptrgcls = msg->class;
|
parm->db.iptrgcls = msg->class;
|
||||||
}
|
}
|
||||||
rc = iucv_call_b2f0(IUCV_REPLY, parm);
|
rc = iucv_call_b2f0(IUCV_REPLY, parm);
|
||||||
|
out:
|
||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1190,6 +1259,10 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
|
||||||
union iucv_param *parm;
|
union iucv_param *parm;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
parm = iucv_param[smp_processor_id()];
|
parm = iucv_param[smp_processor_id()];
|
||||||
memset(parm, 0, sizeof(union iucv_param));
|
memset(parm, 0, sizeof(union iucv_param));
|
||||||
if (flags & IUCV_IPRMDATA) {
|
if (flags & IUCV_IPRMDATA) {
|
||||||
|
@ -1212,6 +1285,7 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
|
||||||
rc = iucv_call_b2f0(IUCV_SEND, parm);
|
rc = iucv_call_b2f0(IUCV_SEND, parm);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
msg->id = parm->db.ipmsgid;
|
msg->id = parm->db.ipmsgid;
|
||||||
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__iucv_message_send);
|
EXPORT_SYMBOL(__iucv_message_send);
|
||||||
|
@ -1272,6 +1346,10 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
|
if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
parm = iucv_param[smp_processor_id()];
|
parm = iucv_param[smp_processor_id()];
|
||||||
memset(parm, 0, sizeof(union iucv_param));
|
memset(parm, 0, sizeof(union iucv_param));
|
||||||
if (flags & IUCV_IPRMDATA) {
|
if (flags & IUCV_IPRMDATA) {
|
||||||
|
@ -1297,6 +1375,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
|
||||||
rc = iucv_call_b2f0(IUCV_SEND, parm);
|
rc = iucv_call_b2f0(IUCV_SEND, parm);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
msg->id = parm->db.ipmsgid;
|
msg->id = parm->db.ipmsgid;
|
||||||
|
out:
|
||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1740,15 +1819,20 @@ static int __init iucv_init(void)
|
||||||
rc = register_hotcpu_notifier(&iucv_cpu_notifier);
|
rc = register_hotcpu_notifier(&iucv_cpu_notifier);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
rc = register_reboot_notifier(&iucv_reboot_notifier);
|
||||||
|
if (rc)
|
||||||
|
goto out_cpu;
|
||||||
ASCEBC(iucv_error_no_listener, 16);
|
ASCEBC(iucv_error_no_listener, 16);
|
||||||
ASCEBC(iucv_error_no_memory, 16);
|
ASCEBC(iucv_error_no_memory, 16);
|
||||||
ASCEBC(iucv_error_pathid, 16);
|
ASCEBC(iucv_error_pathid, 16);
|
||||||
iucv_available = 1;
|
iucv_available = 1;
|
||||||
rc = bus_register(&iucv_bus);
|
rc = bus_register(&iucv_bus);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_cpu;
|
goto out_reboot;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_reboot:
|
||||||
|
unregister_reboot_notifier(&iucv_reboot_notifier);
|
||||||
out_cpu:
|
out_cpu:
|
||||||
unregister_hotcpu_notifier(&iucv_cpu_notifier);
|
unregister_hotcpu_notifier(&iucv_cpu_notifier);
|
||||||
out_free:
|
out_free:
|
||||||
|
@ -1783,6 +1867,7 @@ static void __exit iucv_exit(void)
|
||||||
list_for_each_entry_safe(p, n, &iucv_work_queue, list)
|
list_for_each_entry_safe(p, n, &iucv_work_queue, list)
|
||||||
kfree(p);
|
kfree(p);
|
||||||
spin_unlock_irq(&iucv_queue_lock);
|
spin_unlock_irq(&iucv_queue_lock);
|
||||||
|
unregister_reboot_notifier(&iucv_reboot_notifier);
|
||||||
unregister_hotcpu_notifier(&iucv_cpu_notifier);
|
unregister_hotcpu_notifier(&iucv_cpu_notifier);
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
kfree(iucv_param_irq[cpu]);
|
kfree(iucv_param_irq[cpu]);
|
||||||
|
|
Loading…
Reference in a new issue