aboutsummaryrefslogtreecommitdiffstats
path: root/net/iucv/iucv.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/iucv/iucv.c')
-rw-r--r--net/iucv/iucv.c311
1 files changed, 299 insertions, 12 deletions
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index a35240f61ec..c833481d32e 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
@@ -10,6 +11,8 @@
10 * Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) 11 * Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
11 * Rewritten for af_iucv: 12 * Rewritten for af_iucv:
12 * Martin Schwidefsky <schwidefsky@de.ibm.com> 13 * Martin Schwidefsky <schwidefsky@de.ibm.com>
14 * PM functions:
15 * Ursula Braun (ursula.braun@de.ibm.com)
13 * 16 *
14 * Documentation used: 17 * Documentation used:
15 * The original source 18 * The original source
@@ -45,6 +48,7 @@
45#include <linux/err.h> 48#include <linux/err.h>
46#include <linux/device.h> 49#include <linux/device.h>
47#include <linux/cpu.h> 50#include <linux/cpu.h>
51#include <linux/reboot.h>
48#include <net/iucv/iucv.h> 52#include <net/iucv/iucv.h>
49#include <asm/atomic.h> 53#include <asm/atomic.h>
50#include <asm/ebcdic.h> 54#include <asm/ebcdic.h>
@@ -75,9 +79,24 @@ static int iucv_bus_match(struct device *dev, struct device_driver *drv)
75 return 0; 79 return 0;
76} 80}
77 81
82static int iucv_pm_prepare(struct device *);
83static void iucv_pm_complete(struct device *);
84static int iucv_pm_freeze(struct device *);
85static int iucv_pm_thaw(struct device *);
86static int iucv_pm_restore(struct device *);
87
88static struct dev_pm_ops iucv_pm_ops = {
89 .prepare = iucv_pm_prepare,
90 .complete = iucv_pm_complete,
91 .freeze = iucv_pm_freeze,
92 .thaw = iucv_pm_thaw,
93 .restore = iucv_pm_restore,
94};
95
78struct bus_type iucv_bus = { 96struct bus_type iucv_bus = {
79 .name = "iucv", 97 .name = "iucv",
80 .match = iucv_bus_match, 98 .match = iucv_bus_match,
99 .pm = &iucv_pm_ops,
81}; 100};
82EXPORT_SYMBOL(iucv_bus); 101EXPORT_SYMBOL(iucv_bus);
83 102
@@ -147,6 +166,7 @@ enum iucv_command_codes {
147 IUCV_RESUME = 14, 166 IUCV_RESUME = 14,
148 IUCV_SEVER = 15, 167 IUCV_SEVER = 15,
149 IUCV_SETMASK = 16, 168 IUCV_SETMASK = 16,
169 IUCV_SETCONTROLMASK = 17,
150}; 170};
151 171
152/* 172/*
@@ -280,6 +300,7 @@ union iucv_param {
280 * Anchor for per-cpu IUCV command parameter block. 300 * Anchor for per-cpu IUCV command parameter block.
281 */ 301 */
282static union iucv_param *iucv_param[NR_CPUS]; 302static union iucv_param *iucv_param[NR_CPUS];
303static union iucv_param *iucv_param_irq[NR_CPUS];
283 304
284/** 305/**
285 * iucv_call_b2f0 306 * iucv_call_b2f0
@@ -358,11 +379,23 @@ static void iucv_allow_cpu(void *data)
358 * 0x10 - Flag to allow priority message completion interrupts 379 * 0x10 - Flag to allow priority message completion interrupts
359 * 0x08 - Flag to allow IUCV control interrupts 380 * 0x08 - Flag to allow IUCV control interrupts
360 */ 381 */
361 parm = iucv_param[cpu]; 382 parm = iucv_param_irq[cpu];
362 memset(parm, 0, sizeof(union iucv_param)); 383 memset(parm, 0, sizeof(union iucv_param));
363 parm->set_mask.ipmask = 0xf8; 384 parm->set_mask.ipmask = 0xf8;
364 iucv_call_b2f0(IUCV_SETMASK, parm); 385 iucv_call_b2f0(IUCV_SETMASK, parm);
365 386
387 /*
388 * Enable all iucv control interrupts.
389 * ipmask contains bits for the different interrupts
390 * 0x80 - Flag to allow pending connections interrupts
391 * 0x40 - Flag to allow connection complete interrupts
392 * 0x20 - Flag to allow connection severed interrupts
393 * 0x10 - Flag to allow connection quiesced interrupts
394 * 0x08 - Flag to allow connection resumed interrupts
395 */
396 memset(parm, 0, sizeof(union iucv_param));
397 parm->set_mask.ipmask = 0xf8;
398 iucv_call_b2f0(IUCV_SETCONTROLMASK, parm);
366 /* Set indication that iucv interrupts are allowed for this cpu. */ 399 /* Set indication that iucv interrupts are allowed for this cpu. */
367 cpu_set(cpu, iucv_irq_cpumask); 400 cpu_set(cpu, iucv_irq_cpumask);
368} 401}
@@ -379,7 +412,7 @@ static void iucv_block_cpu(void *data)
379 union iucv_param *parm; 412 union iucv_param *parm;
380 413
381 /* Disable all iucv interrupts. */ 414 /* Disable all iucv interrupts. */
382 parm = iucv_param[cpu]; 415 parm = iucv_param_irq[cpu];
383 memset(parm, 0, sizeof(union iucv_param)); 416 memset(parm, 0, sizeof(union iucv_param));
384 iucv_call_b2f0(IUCV_SETMASK, parm); 417 iucv_call_b2f0(IUCV_SETMASK, parm);
385 418
@@ -388,6 +421,31 @@ static void iucv_block_cpu(void *data)
388} 421}
389 422
390/** 423/**
424 * iucv_block_cpu_almost
425 * @data: unused
426 *
427 * Allow connection-severed interrupts only on this cpu.
428 */
429static void iucv_block_cpu_almost(void *data)
430{
431 int cpu = smp_processor_id();
432 union iucv_param *parm;
433
434 /* Allow iucv control interrupts only */
435 parm = iucv_param_irq[cpu];
436 memset(parm, 0, sizeof(union iucv_param));
437 parm->set_mask.ipmask = 0x08;
438 iucv_call_b2f0(IUCV_SETMASK, parm);
439 /* Allow iucv-severed interrupt only */
440 memset(parm, 0, sizeof(union iucv_param));
441 parm->set_mask.ipmask = 0x20;
442 iucv_call_b2f0(IUCV_SETCONTROLMASK, parm);
443
444 /* Clear indication that iucv interrupts are allowed for this cpu. */
445 cpu_clear(cpu, iucv_irq_cpumask);
446}
447
448/**
391 * iucv_declare_cpu 449 * iucv_declare_cpu
392 * @data: unused 450 * @data: unused
393 * 451 *
@@ -403,7 +461,7 @@ static void iucv_declare_cpu(void *data)
403 return; 461 return;
404 462
405 /* Declare interrupt buffer. */ 463 /* Declare interrupt buffer. */
406 parm = iucv_param[cpu]; 464 parm = iucv_param_irq[cpu];
407 memset(parm, 0, sizeof(union iucv_param)); 465 memset(parm, 0, sizeof(union iucv_param));
408 parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]); 466 parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]);
409 rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm); 467 rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm);
@@ -460,7 +518,7 @@ static void iucv_retrieve_cpu(void *data)
460 iucv_block_cpu(NULL); 518 iucv_block_cpu(NULL);
461 519
462 /* Retrieve interrupt buffer. */ 520 /* Retrieve interrupt buffer. */
463 parm = iucv_param[cpu]; 521 parm = iucv_param_irq[cpu];
464 iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm); 522 iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm);
465 523
466 /* Clear indication that an iucv buffer exists for this cpu. */ 524 /* Clear indication that an iucv buffer exists for this cpu. */
@@ -574,11 +632,22 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
574 iucv_irq_data[cpu] = NULL; 632 iucv_irq_data[cpu] = NULL;
575 return NOTIFY_BAD; 633 return NOTIFY_BAD;
576 } 634 }
635 iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
636 GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
637 if (!iucv_param_irq[cpu]) {
638 kfree(iucv_param[cpu]);
639 iucv_param[cpu] = NULL;
640 kfree(iucv_irq_data[cpu]);
641 iucv_irq_data[cpu] = NULL;
642 return NOTIFY_BAD;
643 }
577 break; 644 break;
578 case CPU_UP_CANCELED: 645 case CPU_UP_CANCELED:
579 case CPU_UP_CANCELED_FROZEN: 646 case CPU_UP_CANCELED_FROZEN:
580 case CPU_DEAD: 647 case CPU_DEAD:
581 case CPU_DEAD_FROZEN: 648 case CPU_DEAD_FROZEN:
649 kfree(iucv_param_irq[cpu]);
650 iucv_param_irq[cpu] = NULL;
582 kfree(iucv_param[cpu]); 651 kfree(iucv_param[cpu]);
583 iucv_param[cpu] = NULL; 652 iucv_param[cpu] = NULL;
584 kfree(iucv_irq_data[cpu]); 653 kfree(iucv_irq_data[cpu]);
@@ -625,7 +694,7 @@ static int iucv_sever_pathid(u16 pathid, u8 userdata[16])
625{ 694{
626 union iucv_param *parm; 695 union iucv_param *parm;
627 696
628 parm = iucv_param[smp_processor_id()]; 697 parm = iucv_param_irq[smp_processor_id()];
629 memset(parm, 0, sizeof(union iucv_param)); 698 memset(parm, 0, sizeof(union iucv_param));
630 if (userdata) 699 if (userdata)
631 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); 700 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
@@ -746,6 +815,28 @@ void iucv_unregister(struct iucv_handler *handler, int smp)
746} 815}
747EXPORT_SYMBOL(iucv_unregister); 816EXPORT_SYMBOL(iucv_unregister);
748 817
818static int iucv_reboot_event(struct notifier_block *this,
819 unsigned long event, void *ptr)
820{
821 int i, rc;
822
823 get_online_cpus();
824 on_each_cpu(iucv_block_cpu, NULL, 1);
825 preempt_disable();
826 for (i = 0; i < iucv_max_pathid; i++) {
827 if (iucv_path_table[i])
828 rc = iucv_sever_pathid(i, NULL);
829 }
830 preempt_enable();
831 put_online_cpus();
832 iucv_disable();
833 return NOTIFY_DONE;
834}
835
836static struct notifier_block iucv_reboot_notifier = {
837 .notifier_call = iucv_reboot_event,
838};
839
749/** 840/**
750 * iucv_path_accept 841 * iucv_path_accept
751 * @path: address of iucv path structure 842 * @path: address of iucv path structure
@@ -765,6 +856,10 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
765 int rc; 856 int rc;
766 857
767 local_bh_disable(); 858 local_bh_disable();
859 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
860 rc = -EIO;
861 goto out;
862 }
768 /* Prepare parameter block. */ 863 /* Prepare parameter block. */
769 parm = iucv_param[smp_processor_id()]; 864 parm = iucv_param[smp_processor_id()];
770 memset(parm, 0, sizeof(union iucv_param)); 865 memset(parm, 0, sizeof(union iucv_param));
@@ -780,6 +875,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
780 path->msglim = parm->ctrl.ipmsglim; 875 path->msglim = parm->ctrl.ipmsglim;
781 path->flags = parm->ctrl.ipflags1; 876 path->flags = parm->ctrl.ipflags1;
782 } 877 }
878out:
783 local_bh_enable(); 879 local_bh_enable();
784 return rc; 880 return rc;
785} 881}
@@ -809,6 +905,10 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
809 905
810 spin_lock_bh(&iucv_table_lock); 906 spin_lock_bh(&iucv_table_lock);
811 iucv_cleanup_queue(); 907 iucv_cleanup_queue();
908 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
909 rc = -EIO;
910 goto out;
911 }
812 parm = iucv_param[smp_processor_id()]; 912 parm = iucv_param[smp_processor_id()];
813 memset(parm, 0, sizeof(union iucv_param)); 913 memset(parm, 0, sizeof(union iucv_param));
814 parm->ctrl.ipmsglim = path->msglim; 914 parm->ctrl.ipmsglim = path->msglim;
@@ -843,6 +943,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
843 rc = -EIO; 943 rc = -EIO;
844 } 944 }
845 } 945 }
946out:
846 spin_unlock_bh(&iucv_table_lock); 947 spin_unlock_bh(&iucv_table_lock);
847 return rc; 948 return rc;
848} 949}
@@ -864,12 +965,17 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16])
864 int rc; 965 int rc;
865 966
866 local_bh_disable(); 967 local_bh_disable();
968 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
969 rc = -EIO;
970 goto out;
971 }
867 parm = iucv_param[smp_processor_id()]; 972 parm = iucv_param[smp_processor_id()];
868 memset(parm, 0, sizeof(union iucv_param)); 973 memset(parm, 0, sizeof(union iucv_param));
869 if (userdata) 974 if (userdata)
870 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); 975 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
871 parm->ctrl.ippathid = path->pathid; 976 parm->ctrl.ippathid = path->pathid;
872 rc = iucv_call_b2f0(IUCV_QUIESCE, parm); 977 rc = iucv_call_b2f0(IUCV_QUIESCE, parm);
978out:
873 local_bh_enable(); 979 local_bh_enable();
874 return rc; 980 return rc;
875} 981}
@@ -891,12 +997,17 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16])
891 int rc; 997 int rc;
892 998
893 local_bh_disable(); 999 local_bh_disable();
1000 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1001 rc = -EIO;
1002 goto out;
1003 }
894 parm = iucv_param[smp_processor_id()]; 1004 parm = iucv_param[smp_processor_id()];
895 memset(parm, 0, sizeof(union iucv_param)); 1005 memset(parm, 0, sizeof(union iucv_param));
896 if (userdata) 1006 if (userdata)
897 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); 1007 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
898 parm->ctrl.ippathid = path->pathid; 1008 parm->ctrl.ippathid = path->pathid;
899 rc = iucv_call_b2f0(IUCV_RESUME, parm); 1009 rc = iucv_call_b2f0(IUCV_RESUME, parm);
1010out:
900 local_bh_enable(); 1011 local_bh_enable();
901 return rc; 1012 return rc;
902} 1013}
@@ -915,15 +1026,18 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
915 int rc; 1026 int rc;
916 1027
917 preempt_disable(); 1028 preempt_disable();
1029 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1030 rc = -EIO;
1031 goto out;
1032 }
918 if (iucv_active_cpu != smp_processor_id()) 1033 if (iucv_active_cpu != smp_processor_id())
919 spin_lock_bh(&iucv_table_lock); 1034 spin_lock_bh(&iucv_table_lock);
920 rc = iucv_sever_pathid(path->pathid, userdata); 1035 rc = iucv_sever_pathid(path->pathid, userdata);
921 if (!rc) { 1036 iucv_path_table[path->pathid] = NULL;
922 iucv_path_table[path->pathid] = NULL; 1037 list_del_init(&path->list);
923 list_del_init(&path->list);
924 }
925 if (iucv_active_cpu != smp_processor_id()) 1038 if (iucv_active_cpu != smp_processor_id())
926 spin_unlock_bh(&iucv_table_lock); 1039 spin_unlock_bh(&iucv_table_lock);
1040out:
927 preempt_enable(); 1041 preempt_enable();
928 return rc; 1042 return rc;
929} 1043}
@@ -946,6 +1060,10 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
946 int rc; 1060 int rc;
947 1061
948 local_bh_disable(); 1062 local_bh_disable();
1063 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1064 rc = -EIO;
1065 goto out;
1066 }
949 parm = iucv_param[smp_processor_id()]; 1067 parm = iucv_param[smp_processor_id()];
950 memset(parm, 0, sizeof(union iucv_param)); 1068 memset(parm, 0, sizeof(union iucv_param));
951 parm->purge.ippathid = path->pathid; 1069 parm->purge.ippathid = path->pathid;
@@ -957,6 +1075,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
957 msg->audit = (*(u32 *) &parm->purge.ipaudit) >> 8; 1075 msg->audit = (*(u32 *) &parm->purge.ipaudit) >> 8;
958 msg->tag = parm->purge.ipmsgtag; 1076 msg->tag = parm->purge.ipmsgtag;
959 } 1077 }
1078out:
960 local_bh_enable(); 1079 local_bh_enable();
961 return rc; 1080 return rc;
962} 1081}
@@ -1033,6 +1152,10 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
1033 if (msg->flags & IUCV_IPRMDATA) 1152 if (msg->flags & IUCV_IPRMDATA)
1034 return iucv_message_receive_iprmdata(path, msg, flags, 1153 return iucv_message_receive_iprmdata(path, msg, flags,
1035 buffer, size, residual); 1154 buffer, size, residual);
1155 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1156 rc = -EIO;
1157 goto out;
1158 }
1036 parm = iucv_param[smp_processor_id()]; 1159 parm = iucv_param[smp_processor_id()];
1037 memset(parm, 0, sizeof(union iucv_param)); 1160 memset(parm, 0, sizeof(union iucv_param));
1038 parm->db.ipbfadr1 = (u32)(addr_t) buffer; 1161 parm->db.ipbfadr1 = (u32)(addr_t) buffer;
@@ -1048,6 +1171,7 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
1048 if (residual) 1171 if (residual)
1049 *residual = parm->db.ipbfln1f; 1172 *residual = parm->db.ipbfln1f;
1050 } 1173 }
1174out:
1051 return rc; 1175 return rc;
1052} 1176}
1053EXPORT_SYMBOL(__iucv_message_receive); 1177EXPORT_SYMBOL(__iucv_message_receive);
@@ -1101,6 +1225,10 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
1101 int rc; 1225 int rc;
1102 1226
1103 local_bh_disable(); 1227 local_bh_disable();
1228 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1229 rc = -EIO;
1230 goto out;
1231 }
1104 parm = iucv_param[smp_processor_id()]; 1232 parm = iucv_param[smp_processor_id()];
1105 memset(parm, 0, sizeof(union iucv_param)); 1233 memset(parm, 0, sizeof(union iucv_param));
1106 parm->db.ippathid = path->pathid; 1234 parm->db.ippathid = path->pathid;
@@ -1108,6 +1236,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
1108 parm->db.iptrgcls = msg->class; 1236 parm->db.iptrgcls = msg->class;
1109 parm->db.ipflags1 = (IUCV_IPTRGCLS | IUCV_IPFGMID | IUCV_IPFGPID); 1237 parm->db.ipflags1 = (IUCV_IPTRGCLS | IUCV_IPFGMID | IUCV_IPFGPID);
1110 rc = iucv_call_b2f0(IUCV_REJECT, parm); 1238 rc = iucv_call_b2f0(IUCV_REJECT, parm);
1239out:
1111 local_bh_enable(); 1240 local_bh_enable();
1112 return rc; 1241 return rc;
1113} 1242}
@@ -1135,6 +1264,10 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
1135 int rc; 1264 int rc;
1136 1265
1137 local_bh_disable(); 1266 local_bh_disable();
1267 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1268 rc = -EIO;
1269 goto out;
1270 }
1138 parm = iucv_param[smp_processor_id()]; 1271 parm = iucv_param[smp_processor_id()];
1139 memset(parm, 0, sizeof(union iucv_param)); 1272 memset(parm, 0, sizeof(union iucv_param));
1140 if (flags & IUCV_IPRMDATA) { 1273 if (flags & IUCV_IPRMDATA) {
@@ -1152,6 +1285,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
1152 parm->db.iptrgcls = msg->class; 1285 parm->db.iptrgcls = msg->class;
1153 } 1286 }
1154 rc = iucv_call_b2f0(IUCV_REPLY, parm); 1287 rc = iucv_call_b2f0(IUCV_REPLY, parm);
1288out:
1155 local_bh_enable(); 1289 local_bh_enable();
1156 return rc; 1290 return rc;
1157} 1291}
@@ -1180,6 +1314,10 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
1180 union iucv_param *parm; 1314 union iucv_param *parm;
1181 int rc; 1315 int rc;
1182 1316
1317 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1318 rc = -EIO;
1319 goto out;
1320 }
1183 parm = iucv_param[smp_processor_id()]; 1321 parm = iucv_param[smp_processor_id()];
1184 memset(parm, 0, sizeof(union iucv_param)); 1322 memset(parm, 0, sizeof(union iucv_param));
1185 if (flags & IUCV_IPRMDATA) { 1323 if (flags & IUCV_IPRMDATA) {
@@ -1202,6 +1340,7 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
1202 rc = iucv_call_b2f0(IUCV_SEND, parm); 1340 rc = iucv_call_b2f0(IUCV_SEND, parm);
1203 if (!rc) 1341 if (!rc)
1204 msg->id = parm->db.ipmsgid; 1342 msg->id = parm->db.ipmsgid;
1343out:
1205 return rc; 1344 return rc;
1206} 1345}
1207EXPORT_SYMBOL(__iucv_message_send); 1346EXPORT_SYMBOL(__iucv_message_send);
@@ -1262,6 +1401,10 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
1262 int rc; 1401 int rc;
1263 1402
1264 local_bh_disable(); 1403 local_bh_disable();
1404 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1405 rc = -EIO;
1406 goto out;
1407 }
1265 parm = iucv_param[smp_processor_id()]; 1408 parm = iucv_param[smp_processor_id()];
1266 memset(parm, 0, sizeof(union iucv_param)); 1409 memset(parm, 0, sizeof(union iucv_param));
1267 if (flags & IUCV_IPRMDATA) { 1410 if (flags & IUCV_IPRMDATA) {
@@ -1287,6 +1430,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
1287 rc = iucv_call_b2f0(IUCV_SEND, parm); 1430 rc = iucv_call_b2f0(IUCV_SEND, parm);
1288 if (!rc) 1431 if (!rc)
1289 msg->id = parm->db.ipmsgid; 1432 msg->id = parm->db.ipmsgid;
1433out:
1290 local_bh_enable(); 1434 local_bh_enable();
1291 return rc; 1435 return rc;
1292} 1436}
@@ -1378,6 +1522,8 @@ static void iucv_path_complete(struct iucv_irq_data *data)
1378 struct iucv_path_complete *ipc = (void *) data; 1522 struct iucv_path_complete *ipc = (void *) data;
1379 struct iucv_path *path = iucv_path_table[ipc->ippathid]; 1523 struct iucv_path *path = iucv_path_table[ipc->ippathid];
1380 1524
1525 if (path)
1526 path->flags = ipc->ipflags1;
1381 if (path && path->handler && path->handler->path_complete) 1527 if (path && path->handler && path->handler->path_complete)
1382 path->handler->path_complete(path, ipc->ipuser); 1528 path->handler->path_complete(path, ipc->ipuser);
1383} 1529}
@@ -1413,7 +1559,7 @@ static void iucv_path_severed(struct iucv_irq_data *data)
1413 else { 1559 else {
1414 iucv_sever_pathid(path->pathid, NULL); 1560 iucv_sever_pathid(path->pathid, NULL);
1415 iucv_path_table[path->pathid] = NULL; 1561 iucv_path_table[path->pathid] = NULL;
1416 list_del_init(&path->list); 1562 list_del(&path->list);
1417 iucv_path_free(path); 1563 iucv_path_free(path);
1418 } 1564 }
1419} 1565}
@@ -1675,6 +1821,130 @@ static void iucv_external_interrupt(u16 code)
1675 spin_unlock(&iucv_queue_lock); 1821 spin_unlock(&iucv_queue_lock);
1676} 1822}
1677 1823
1824static int iucv_pm_prepare(struct device *dev)
1825{
1826 int rc = 0;
1827
1828#ifdef CONFIG_PM_DEBUG
1829 printk(KERN_INFO "iucv_pm_prepare\n");
1830#endif
1831 if (dev->driver && dev->driver->pm && dev->driver->pm->prepare)
1832 rc = dev->driver->pm->prepare(dev);
1833 return rc;
1834}
1835
1836static void iucv_pm_complete(struct device *dev)
1837{
1838#ifdef CONFIG_PM_DEBUG
1839 printk(KERN_INFO "iucv_pm_complete\n");
1840#endif
1841 if (dev->driver && dev->driver->pm && dev->driver->pm->complete)
1842 dev->driver->pm->complete(dev);
1843}
1844
1845/**
1846 * iucv_path_table_empty() - determine if iucv path table is empty
1847 *
1848 * Returns 0 if there are still iucv pathes defined
1849 * 1 if there are no iucv pathes defined
1850 */
1851int iucv_path_table_empty(void)
1852{
1853 int i;
1854
1855 for (i = 0; i < iucv_max_pathid; i++) {
1856 if (iucv_path_table[i])
1857 return 0;
1858 }
1859 return 1;
1860}
1861
1862/**
1863 * iucv_pm_freeze() - Freeze PM callback
1864 * @dev: iucv-based device
1865 *
1866 * disable iucv interrupts
1867 * invoke callback function of the iucv-based driver
1868 * shut down iucv, if no iucv-pathes are established anymore
1869 */
1870static int iucv_pm_freeze(struct device *dev)
1871{
1872 int cpu;
1873 int rc = 0;
1874
1875#ifdef CONFIG_PM_DEBUG
1876 printk(KERN_WARNING "iucv_pm_freeze\n");
1877#endif
1878 for_each_cpu_mask_nr(cpu, iucv_irq_cpumask)
1879 smp_call_function_single(cpu, iucv_block_cpu_almost, NULL, 1);
1880 if (dev->driver && dev->driver->pm && dev->driver->pm->freeze)
1881 rc = dev->driver->pm->freeze(dev);
1882 if (iucv_path_table_empty())
1883 iucv_disable();
1884 return rc;
1885}
1886
1887/**
1888 * iucv_pm_thaw() - Thaw PM callback
1889 * @dev: iucv-based device
1890 *
1891 * make iucv ready for use again: allocate path table, declare interrupt buffers
1892 * and enable iucv interrupts
1893 * invoke callback function of the iucv-based driver
1894 */
1895static int iucv_pm_thaw(struct device *dev)
1896{
1897 int rc = 0;
1898
1899#ifdef CONFIG_PM_DEBUG
1900 printk(KERN_WARNING "iucv_pm_thaw\n");
1901#endif
1902 if (!iucv_path_table) {
1903 rc = iucv_enable();
1904 if (rc)
1905 goto out;
1906 }
1907 if (cpus_empty(iucv_irq_cpumask)) {
1908 if (iucv_nonsmp_handler)
1909 /* enable interrupts on one cpu */
1910 iucv_allow_cpu(NULL);
1911 else
1912 /* enable interrupts on all cpus */
1913 iucv_setmask_mp();
1914 }
1915 if (dev->driver && dev->driver->pm && dev->driver->pm->thaw)
1916 rc = dev->driver->pm->thaw(dev);
1917out:
1918 return rc;
1919}
1920
1921/**
1922 * iucv_pm_restore() - Restore PM callback
1923 * @dev: iucv-based device
1924 *
1925 * make iucv ready for use again: allocate path table, declare interrupt buffers
1926 * and enable iucv interrupts
1927 * invoke callback function of the iucv-based driver
1928 */
1929static int iucv_pm_restore(struct device *dev)
1930{
1931 int rc = 0;
1932
1933#ifdef CONFIG_PM_DEBUG
1934 printk(KERN_WARNING "iucv_pm_restore %p\n", iucv_path_table);
1935#endif
1936 if (cpus_empty(iucv_irq_cpumask)) {
1937 rc = iucv_query_maxconn();
1938 rc = iucv_enable();
1939 if (rc)
1940 goto out;
1941 }
1942 if (dev->driver && dev->driver->pm && dev->driver->pm->restore)
1943 rc = dev->driver->pm->restore(dev);
1944out:
1945 return rc;
1946}
1947
1678/** 1948/**
1679 * iucv_init 1949 * iucv_init
1680 * 1950 *
@@ -1717,23 +1987,37 @@ static int __init iucv_init(void)
1717 rc = -ENOMEM; 1987 rc = -ENOMEM;
1718 goto out_free; 1988 goto out_free;
1719 } 1989 }
1990 iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
1991 GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
1992 if (!iucv_param_irq[cpu]) {
1993 rc = -ENOMEM;
1994 goto out_free;
1995 }
1996
1720 } 1997 }
1721 rc = register_hotcpu_notifier(&iucv_cpu_notifier); 1998 rc = register_hotcpu_notifier(&iucv_cpu_notifier);
1722 if (rc) 1999 if (rc)
1723 goto out_free; 2000 goto out_free;
2001 rc = register_reboot_notifier(&iucv_reboot_notifier);
2002 if (rc)
2003 goto out_cpu;
1724 ASCEBC(iucv_error_no_listener, 16); 2004 ASCEBC(iucv_error_no_listener, 16);
1725 ASCEBC(iucv_error_no_memory, 16); 2005 ASCEBC(iucv_error_no_memory, 16);
1726 ASCEBC(iucv_error_pathid, 16); 2006 ASCEBC(iucv_error_pathid, 16);
1727 iucv_available = 1; 2007 iucv_available = 1;
1728 rc = bus_register(&iucv_bus); 2008 rc = bus_register(&iucv_bus);
1729 if (rc) 2009 if (rc)
1730 goto out_cpu; 2010 goto out_reboot;
1731 return 0; 2011 return 0;
1732 2012
2013out_reboot:
2014 unregister_reboot_notifier(&iucv_reboot_notifier);
1733out_cpu: 2015out_cpu:
1734 unregister_hotcpu_notifier(&iucv_cpu_notifier); 2016 unregister_hotcpu_notifier(&iucv_cpu_notifier);
1735out_free: 2017out_free:
1736 for_each_possible_cpu(cpu) { 2018 for_each_possible_cpu(cpu) {
2019 kfree(iucv_param_irq[cpu]);
2020 iucv_param_irq[cpu] = NULL;
1737 kfree(iucv_param[cpu]); 2021 kfree(iucv_param[cpu]);
1738 iucv_param[cpu] = NULL; 2022 iucv_param[cpu] = NULL;
1739 kfree(iucv_irq_data[cpu]); 2023 kfree(iucv_irq_data[cpu]);
@@ -1762,8 +2046,11 @@ static void __exit iucv_exit(void)
1762 list_for_each_entry_safe(p, n, &iucv_work_queue, list) 2046 list_for_each_entry_safe(p, n, &iucv_work_queue, list)
1763 kfree(p); 2047 kfree(p);
1764 spin_unlock_irq(&iucv_queue_lock); 2048 spin_unlock_irq(&iucv_queue_lock);
2049 unregister_reboot_notifier(&iucv_reboot_notifier);
1765 unregister_hotcpu_notifier(&iucv_cpu_notifier); 2050 unregister_hotcpu_notifier(&iucv_cpu_notifier);
1766 for_each_possible_cpu(cpu) { 2051 for_each_possible_cpu(cpu) {
2052 kfree(iucv_param_irq[cpu]);
2053 iucv_param_irq[cpu] = NULL;
1767 kfree(iucv_param[cpu]); 2054 kfree(iucv_param[cpu]);
1768 iucv_param[cpu] = NULL; 2055 iucv_param[cpu] = NULL;
1769 kfree(iucv_irq_data[cpu]); 2056 kfree(iucv_irq_data[cpu]);