aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/iucv/iucv.c89
1 files changed, 87 insertions, 2 deletions
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 61e8038a55ee..0e9f212dd928 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -1,7 +1,8 @@
1/* 1/*
2 * IUCV base infrastructure. 2 * IUCV base infrastructure.
3 * 3 *
4 * Copyright 2001, 2006 IBM Deutschland Entwicklung GmbH, IBM Corporation 4 * Copyright IBM Corp. 2001, 2009
5 *
5 * Author(s): 6 * Author(s):
6 * Original source: 7 * Original source:
7 * Alan Altmark (Alan_Altmark@us.ibm.com) Sept. 2000 8 * Alan Altmark (Alan_Altmark@us.ibm.com) Sept. 2000
@@ -45,6 +46,7 @@
45#include <linux/err.h> 46#include <linux/err.h>
46#include <linux/device.h> 47#include <linux/device.h>
47#include <linux/cpu.h> 48#include <linux/cpu.h>
49#include <linux/reboot.h>
48#include <net/iucv/iucv.h> 50#include <net/iucv/iucv.h>
49#include <asm/atomic.h> 51#include <asm/atomic.h>
50#include <asm/ebcdic.h> 52#include <asm/ebcdic.h>
@@ -758,6 +760,28 @@ void iucv_unregister(struct iucv_handler *handler, int smp)
758} 760}
759EXPORT_SYMBOL(iucv_unregister); 761EXPORT_SYMBOL(iucv_unregister);
760 762
763static int iucv_reboot_event(struct notifier_block *this,
764 unsigned long event, void *ptr)
765{
766 int i, rc;
767
768 get_online_cpus();
769 on_each_cpu(iucv_block_cpu, NULL, 1);
770 preempt_disable();
771 for (i = 0; i < iucv_max_pathid; i++) {
772 if (iucv_path_table[i])
773 rc = iucv_sever_pathid(i, NULL);
774 }
775 preempt_enable();
776 put_online_cpus();
777 iucv_disable();
778 return NOTIFY_DONE;
779}
780
781static struct notifier_block iucv_reboot_notifier = {
782 .notifier_call = iucv_reboot_event,
783};
784
761/** 785/**
762 * iucv_path_accept 786 * iucv_path_accept
763 * @path: address of iucv path structure 787 * @path: address of iucv path structure
@@ -777,6 +801,10 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
777 int rc; 801 int rc;
778 802
779 local_bh_disable(); 803 local_bh_disable();
804 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
805 rc = -EIO;
806 goto out;
807 }
780 /* Prepare parameter block. */ 808 /* Prepare parameter block. */
781 parm = iucv_param[smp_processor_id()]; 809 parm = iucv_param[smp_processor_id()];
782 memset(parm, 0, sizeof(union iucv_param)); 810 memset(parm, 0, sizeof(union iucv_param));
@@ -792,6 +820,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
792 path->msglim = parm->ctrl.ipmsglim; 820 path->msglim = parm->ctrl.ipmsglim;
793 path->flags = parm->ctrl.ipflags1; 821 path->flags = parm->ctrl.ipflags1;
794 } 822 }
823out:
795 local_bh_enable(); 824 local_bh_enable();
796 return rc; 825 return rc;
797} 826}
@@ -821,6 +850,10 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
821 850
822 spin_lock_bh(&iucv_table_lock); 851 spin_lock_bh(&iucv_table_lock);
823 iucv_cleanup_queue(); 852 iucv_cleanup_queue();
853 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
854 rc = -EIO;
855 goto out;
856 }
824 parm = iucv_param[smp_processor_id()]; 857 parm = iucv_param[smp_processor_id()];
825 memset(parm, 0, sizeof(union iucv_param)); 858 memset(parm, 0, sizeof(union iucv_param));
826 parm->ctrl.ipmsglim = path->msglim; 859 parm->ctrl.ipmsglim = path->msglim;
@@ -855,6 +888,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
855 rc = -EIO; 888 rc = -EIO;
856 } 889 }
857 } 890 }
891out:
858 spin_unlock_bh(&iucv_table_lock); 892 spin_unlock_bh(&iucv_table_lock);
859 return rc; 893 return rc;
860} 894}
@@ -876,12 +910,17 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16])
876 int rc; 910 int rc;
877 911
878 local_bh_disable(); 912 local_bh_disable();
913 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
914 rc = -EIO;
915 goto out;
916 }
879 parm = iucv_param[smp_processor_id()]; 917 parm = iucv_param[smp_processor_id()];
880 memset(parm, 0, sizeof(union iucv_param)); 918 memset(parm, 0, sizeof(union iucv_param));
881 if (userdata) 919 if (userdata)
882 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); 920 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
883 parm->ctrl.ippathid = path->pathid; 921 parm->ctrl.ippathid = path->pathid;
884 rc = iucv_call_b2f0(IUCV_QUIESCE, parm); 922 rc = iucv_call_b2f0(IUCV_QUIESCE, parm);
923out:
885 local_bh_enable(); 924 local_bh_enable();
886 return rc; 925 return rc;
887} 926}
@@ -903,12 +942,17 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16])
903 int rc; 942 int rc;
904 943
905 local_bh_disable(); 944 local_bh_disable();
945 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
946 rc = -EIO;
947 goto out;
948 }
906 parm = iucv_param[smp_processor_id()]; 949 parm = iucv_param[smp_processor_id()];
907 memset(parm, 0, sizeof(union iucv_param)); 950 memset(parm, 0, sizeof(union iucv_param));
908 if (userdata) 951 if (userdata)
909 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); 952 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
910 parm->ctrl.ippathid = path->pathid; 953 parm->ctrl.ippathid = path->pathid;
911 rc = iucv_call_b2f0(IUCV_RESUME, parm); 954 rc = iucv_call_b2f0(IUCV_RESUME, parm);
955out:
912 local_bh_enable(); 956 local_bh_enable();
913 return rc; 957 return rc;
914} 958}
@@ -927,6 +971,10 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
927 int rc; 971 int rc;
928 972
929 preempt_disable(); 973 preempt_disable();
974 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
975 rc = -EIO;
976 goto out;
977 }
930 if (iucv_active_cpu != smp_processor_id()) 978 if (iucv_active_cpu != smp_processor_id())
931 spin_lock_bh(&iucv_table_lock); 979 spin_lock_bh(&iucv_table_lock);
932 rc = iucv_sever_pathid(path->pathid, userdata); 980 rc = iucv_sever_pathid(path->pathid, userdata);
@@ -934,6 +982,7 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
934 list_del_init(&path->list); 982 list_del_init(&path->list);
935 if (iucv_active_cpu != smp_processor_id()) 983 if (iucv_active_cpu != smp_processor_id())
936 spin_unlock_bh(&iucv_table_lock); 984 spin_unlock_bh(&iucv_table_lock);
985out:
937 preempt_enable(); 986 preempt_enable();
938 return rc; 987 return rc;
939} 988}
@@ -956,6 +1005,10 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
956 int rc; 1005 int rc;
957 1006
958 local_bh_disable(); 1007 local_bh_disable();
1008 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1009 rc = -EIO;
1010 goto out;
1011 }
959 parm = iucv_param[smp_processor_id()]; 1012 parm = iucv_param[smp_processor_id()];
960 memset(parm, 0, sizeof(union iucv_param)); 1013 memset(parm, 0, sizeof(union iucv_param));
961 parm->purge.ippathid = path->pathid; 1014 parm->purge.ippathid = path->pathid;
@@ -967,6 +1020,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
967 msg->audit = (*(u32 *) &parm->purge.ipaudit) >> 8; 1020 msg->audit = (*(u32 *) &parm->purge.ipaudit) >> 8;
968 msg->tag = parm->purge.ipmsgtag; 1021 msg->tag = parm->purge.ipmsgtag;
969 } 1022 }
1023out:
970 local_bh_enable(); 1024 local_bh_enable();
971 return rc; 1025 return rc;
972} 1026}
@@ -1043,6 +1097,10 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
1043 if (msg->flags & IUCV_IPRMDATA) 1097 if (msg->flags & IUCV_IPRMDATA)
1044 return iucv_message_receive_iprmdata(path, msg, flags, 1098 return iucv_message_receive_iprmdata(path, msg, flags,
1045 buffer, size, residual); 1099 buffer, size, residual);
1100 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1101 rc = -EIO;
1102 goto out;
1103 }
1046 parm = iucv_param[smp_processor_id()]; 1104 parm = iucv_param[smp_processor_id()];
1047 memset(parm, 0, sizeof(union iucv_param)); 1105 memset(parm, 0, sizeof(union iucv_param));
1048 parm->db.ipbfadr1 = (u32)(addr_t) buffer; 1106 parm->db.ipbfadr1 = (u32)(addr_t) buffer;
@@ -1058,6 +1116,7 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
1058 if (residual) 1116 if (residual)
1059 *residual = parm->db.ipbfln1f; 1117 *residual = parm->db.ipbfln1f;
1060 } 1118 }
1119out:
1061 return rc; 1120 return rc;
1062} 1121}
1063EXPORT_SYMBOL(__iucv_message_receive); 1122EXPORT_SYMBOL(__iucv_message_receive);
@@ -1111,6 +1170,10 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
1111 int rc; 1170 int rc;
1112 1171
1113 local_bh_disable(); 1172 local_bh_disable();
1173 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1174 rc = -EIO;
1175 goto out;
1176 }
1114 parm = iucv_param[smp_processor_id()]; 1177 parm = iucv_param[smp_processor_id()];
1115 memset(parm, 0, sizeof(union iucv_param)); 1178 memset(parm, 0, sizeof(union iucv_param));
1116 parm->db.ippathid = path->pathid; 1179 parm->db.ippathid = path->pathid;
@@ -1118,6 +1181,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
1118 parm->db.iptrgcls = msg->class; 1181 parm->db.iptrgcls = msg->class;
1119 parm->db.ipflags1 = (IUCV_IPTRGCLS | IUCV_IPFGMID | IUCV_IPFGPID); 1182 parm->db.ipflags1 = (IUCV_IPTRGCLS | IUCV_IPFGMID | IUCV_IPFGPID);
1120 rc = iucv_call_b2f0(IUCV_REJECT, parm); 1183 rc = iucv_call_b2f0(IUCV_REJECT, parm);
1184out:
1121 local_bh_enable(); 1185 local_bh_enable();
1122 return rc; 1186 return rc;
1123} 1187}
@@ -1145,6 +1209,10 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
1145 int rc; 1209 int rc;
1146 1210
1147 local_bh_disable(); 1211 local_bh_disable();
1212 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1213 rc = -EIO;
1214 goto out;
1215 }
1148 parm = iucv_param[smp_processor_id()]; 1216 parm = iucv_param[smp_processor_id()];
1149 memset(parm, 0, sizeof(union iucv_param)); 1217 memset(parm, 0, sizeof(union iucv_param));
1150 if (flags & IUCV_IPRMDATA) { 1218 if (flags & IUCV_IPRMDATA) {
@@ -1162,6 +1230,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
1162 parm->db.iptrgcls = msg->class; 1230 parm->db.iptrgcls = msg->class;
1163 } 1231 }
1164 rc = iucv_call_b2f0(IUCV_REPLY, parm); 1232 rc = iucv_call_b2f0(IUCV_REPLY, parm);
1233out:
1165 local_bh_enable(); 1234 local_bh_enable();
1166 return rc; 1235 return rc;
1167} 1236}
@@ -1190,6 +1259,10 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
1190 union iucv_param *parm; 1259 union iucv_param *parm;
1191 int rc; 1260 int rc;
1192 1261
1262 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1263 rc = -EIO;
1264 goto out;
1265 }
1193 parm = iucv_param[smp_processor_id()]; 1266 parm = iucv_param[smp_processor_id()];
1194 memset(parm, 0, sizeof(union iucv_param)); 1267 memset(parm, 0, sizeof(union iucv_param));
1195 if (flags & IUCV_IPRMDATA) { 1268 if (flags & IUCV_IPRMDATA) {
@@ -1212,6 +1285,7 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
1212 rc = iucv_call_b2f0(IUCV_SEND, parm); 1285 rc = iucv_call_b2f0(IUCV_SEND, parm);
1213 if (!rc) 1286 if (!rc)
1214 msg->id = parm->db.ipmsgid; 1287 msg->id = parm->db.ipmsgid;
1288out:
1215 return rc; 1289 return rc;
1216} 1290}
1217EXPORT_SYMBOL(__iucv_message_send); 1291EXPORT_SYMBOL(__iucv_message_send);
@@ -1272,6 +1346,10 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
1272 int rc; 1346 int rc;
1273 1347
1274 local_bh_disable(); 1348 local_bh_disable();
1349 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1350 rc = -EIO;
1351 goto out;
1352 }
1275 parm = iucv_param[smp_processor_id()]; 1353 parm = iucv_param[smp_processor_id()];
1276 memset(parm, 0, sizeof(union iucv_param)); 1354 memset(parm, 0, sizeof(union iucv_param));
1277 if (flags & IUCV_IPRMDATA) { 1355 if (flags & IUCV_IPRMDATA) {
@@ -1297,6 +1375,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
1297 rc = iucv_call_b2f0(IUCV_SEND, parm); 1375 rc = iucv_call_b2f0(IUCV_SEND, parm);
1298 if (!rc) 1376 if (!rc)
1299 msg->id = parm->db.ipmsgid; 1377 msg->id = parm->db.ipmsgid;
1378out:
1300 local_bh_enable(); 1379 local_bh_enable();
1301 return rc; 1380 return rc;
1302} 1381}
@@ -1740,15 +1819,20 @@ static int __init iucv_init(void)
1740 rc = register_hotcpu_notifier(&iucv_cpu_notifier); 1819 rc = register_hotcpu_notifier(&iucv_cpu_notifier);
1741 if (rc) 1820 if (rc)
1742 goto out_free; 1821 goto out_free;
1822 rc = register_reboot_notifier(&iucv_reboot_notifier);
1823 if (rc)
1824 goto out_cpu;
1743 ASCEBC(iucv_error_no_listener, 16); 1825 ASCEBC(iucv_error_no_listener, 16);
1744 ASCEBC(iucv_error_no_memory, 16); 1826 ASCEBC(iucv_error_no_memory, 16);
1745 ASCEBC(iucv_error_pathid, 16); 1827 ASCEBC(iucv_error_pathid, 16);
1746 iucv_available = 1; 1828 iucv_available = 1;
1747 rc = bus_register(&iucv_bus); 1829 rc = bus_register(&iucv_bus);
1748 if (rc) 1830 if (rc)
1749 goto out_cpu; 1831 goto out_reboot;
1750 return 0; 1832 return 0;
1751 1833
1834out_reboot:
1835 unregister_reboot_notifier(&iucv_reboot_notifier);
1752out_cpu: 1836out_cpu:
1753 unregister_hotcpu_notifier(&iucv_cpu_notifier); 1837 unregister_hotcpu_notifier(&iucv_cpu_notifier);
1754out_free: 1838out_free:
@@ -1783,6 +1867,7 @@ static void __exit iucv_exit(void)
1783 list_for_each_entry_safe(p, n, &iucv_work_queue, list) 1867 list_for_each_entry_safe(p, n, &iucv_work_queue, list)
1784 kfree(p); 1868 kfree(p);
1785 spin_unlock_irq(&iucv_queue_lock); 1869 spin_unlock_irq(&iucv_queue_lock);
1870 unregister_reboot_notifier(&iucv_reboot_notifier);
1786 unregister_hotcpu_notifier(&iucv_cpu_notifier); 1871 unregister_hotcpu_notifier(&iucv_cpu_notifier);
1787 for_each_possible_cpu(cpu) { 1872 for_each_possible_cpu(cpu) {
1788 kfree(iucv_param_irq[cpu]); 1873 kfree(iucv_param_irq[cpu]);