/*
* IUCV base infrastructure.
*
- * Copyright 2001, 2006 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright IBM Corp. 2001, 2009
+ *
* Author(s):
* Original source:
* Alan Altmark (Alan_Altmark@us.ibm.com) Sept. 2000
#include <linux/err.h>
#include <linux/device.h>
#include <linux/cpu.h>
+#include <linux/reboot.h>
#include <net/iucv/iucv.h>
#include <asm/atomic.h>
#include <asm/ebcdic.h>
}
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
* @path: address of iucv path structure
int rc;
local_bh_disable();
+ if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+ rc = -EIO;
+ goto out;
+ }
/* Prepare parameter block. */
parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
path->msglim = parm->ctrl.ipmsglim;
path->flags = parm->ctrl.ipflags1;
}
+out:
local_bh_enable();
return rc;
}
spin_lock_bh(&iucv_table_lock);
iucv_cleanup_queue();
+ if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+ rc = -EIO;
+ goto out;
+ }
parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
parm->ctrl.ipmsglim = path->msglim;
rc = -EIO;
}
}
+out:
spin_unlock_bh(&iucv_table_lock);
return rc;
}
int rc;
local_bh_disable();
+ if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+ rc = -EIO;
+ goto out;
+ }
parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (userdata)
memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
parm->ctrl.ippathid = path->pathid;
rc = iucv_call_b2f0(IUCV_QUIESCE, parm);
+out:
local_bh_enable();
return rc;
}
int rc;
local_bh_disable();
+ if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+ rc = -EIO;
+ goto out;
+ }
parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (userdata)
memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
parm->ctrl.ippathid = path->pathid;
rc = iucv_call_b2f0(IUCV_RESUME, parm);
+out:
local_bh_enable();
return rc;
}
int rc;
preempt_disable();
+ if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+ rc = -EIO;
+ goto out;
+ }
if (iucv_active_cpu != smp_processor_id())
spin_lock_bh(&iucv_table_lock);
rc = iucv_sever_pathid(path->pathid, userdata);
list_del_init(&path->list);
if (iucv_active_cpu != smp_processor_id())
spin_unlock_bh(&iucv_table_lock);
+out:
preempt_enable();
return rc;
}
int rc;
local_bh_disable();
+ if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+ rc = -EIO;
+ goto out;
+ }
parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
parm->purge.ippathid = path->pathid;
msg->audit = (*(u32 *) &parm->purge.ipaudit) >> 8;
msg->tag = parm->purge.ipmsgtag;
}
+out:
local_bh_enable();
return rc;
}
if (msg->flags & IUCV_IPRMDATA)
return iucv_message_receive_iprmdata(path, msg, flags,
buffer, size, residual);
+ if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+ rc = -EIO;
+ goto out;
+ }
parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
parm->db.ipbfadr1 = (u32)(addr_t) buffer;
if (residual)
*residual = parm->db.ipbfln1f;
}
+out:
return rc;
}
EXPORT_SYMBOL(__iucv_message_receive);
int rc;
local_bh_disable();
+ if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+ rc = -EIO;
+ goto out;
+ }
parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
parm->db.ippathid = path->pathid;
parm->db.iptrgcls = msg->class;
parm->db.ipflags1 = (IUCV_IPTRGCLS | IUCV_IPFGMID | IUCV_IPFGPID);
rc = iucv_call_b2f0(IUCV_REJECT, parm);
+out:
local_bh_enable();
return rc;
}
int rc;
local_bh_disable();
+ if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+ rc = -EIO;
+ goto out;
+ }
parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (flags & IUCV_IPRMDATA) {
parm->db.iptrgcls = msg->class;
}
rc = iucv_call_b2f0(IUCV_REPLY, parm);
+out:
local_bh_enable();
return rc;
}
union iucv_param *parm;
int rc;
+ if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+ rc = -EIO;
+ goto out;
+ }
parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (flags & IUCV_IPRMDATA) {
rc = iucv_call_b2f0(IUCV_SEND, parm);
if (!rc)
msg->id = parm->db.ipmsgid;
+out:
return rc;
}
EXPORT_SYMBOL(__iucv_message_send);
int rc;
local_bh_disable();
+ if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
+ rc = -EIO;
+ goto out;
+ }
parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (flags & IUCV_IPRMDATA) {
rc = iucv_call_b2f0(IUCV_SEND, parm);
if (!rc)
msg->id = parm->db.ipmsgid;
+out:
local_bh_enable();
return rc;
}
rc = register_hotcpu_notifier(&iucv_cpu_notifier);
if (rc)
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_memory, 16);
ASCEBC(iucv_error_pathid, 16);
iucv_available = 1;
rc = bus_register(&iucv_bus);
if (rc)
- goto out_cpu;
+ goto out_reboot;
return 0;
+out_reboot:
+ unregister_reboot_notifier(&iucv_reboot_notifier);
out_cpu:
unregister_hotcpu_notifier(&iucv_cpu_notifier);
out_free:
list_for_each_entry_safe(p, n, &iucv_work_queue, list)
kfree(p);
spin_unlock_irq(&iucv_queue_lock);
+ unregister_reboot_notifier(&iucv_reboot_notifier);
unregister_hotcpu_notifier(&iucv_cpu_notifier);
for_each_possible_cpu(cpu) {
kfree(iucv_param_irq[cpu]);