aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/skbuff.c8
-rw-r--r--net/core/sock.c2
-rw-r--r--net/ipv4/inet_timewait_sock.c3
-rw-r--r--net/iucv/af_iucv.c147
-rw-r--r--net/iucv/iucv.c268
5 files changed, 423 insertions, 5 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 1a94a3037370..5c93435b0347 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -39,6 +39,7 @@
39#include <linux/module.h> 39#include <linux/module.h>
40#include <linux/types.h> 40#include <linux/types.h>
41#include <linux/kernel.h> 41#include <linux/kernel.h>
42#include <linux/kmemcheck.h>
42#include <linux/mm.h> 43#include <linux/mm.h>
43#include <linux/interrupt.h> 44#include <linux/interrupt.h>
44#include <linux/in.h> 45#include <linux/in.h>
@@ -201,6 +202,8 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
201 skb->data = data; 202 skb->data = data;
202 skb_reset_tail_pointer(skb); 203 skb_reset_tail_pointer(skb);
203 skb->end = skb->tail + size; 204 skb->end = skb->tail + size;
205 kmemcheck_annotate_bitfield(skb, flags1);
206 kmemcheck_annotate_bitfield(skb, flags2);
204 /* make sure we initialize shinfo sequentially */ 207 /* make sure we initialize shinfo sequentially */
205 shinfo = skb_shinfo(skb); 208 shinfo = skb_shinfo(skb);
206 atomic_set(&shinfo->dataref, 1); 209 atomic_set(&shinfo->dataref, 1);
@@ -217,6 +220,8 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
217 struct sk_buff *child = skb + 1; 220 struct sk_buff *child = skb + 1;
218 atomic_t *fclone_ref = (atomic_t *) (child + 1); 221 atomic_t *fclone_ref = (atomic_t *) (child + 1);
219 222
223 kmemcheck_annotate_bitfield(child, flags1);
224 kmemcheck_annotate_bitfield(child, flags2);
220 skb->fclone = SKB_FCLONE_ORIG; 225 skb->fclone = SKB_FCLONE_ORIG;
221 atomic_set(fclone_ref, 1); 226 atomic_set(fclone_ref, 1);
222 227
@@ -635,6 +640,9 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
635 n = kmem_cache_alloc(skbuff_head_cache, gfp_mask); 640 n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
636 if (!n) 641 if (!n)
637 return NULL; 642 return NULL;
643
644 kmemcheck_annotate_bitfield(n, flags1);
645 kmemcheck_annotate_bitfield(n, flags2);
638 n->fclone = SKB_FCLONE_UNAVAILABLE; 646 n->fclone = SKB_FCLONE_UNAVAILABLE;
639 } 647 }
640 648
diff --git a/net/core/sock.c b/net/core/sock.c
index 06e26b77ad9e..b0ba569bc973 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -945,6 +945,8 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
945 sk = kmalloc(prot->obj_size, priority); 945 sk = kmalloc(prot->obj_size, priority);
946 946
947 if (sk != NULL) { 947 if (sk != NULL) {
948 kmemcheck_annotate_bitfield(sk, flags);
949
948 if (security_sk_alloc(sk, family, priority)) 950 if (security_sk_alloc(sk, family, priority))
949 goto out_free; 951 goto out_free;
950 952
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index 68a8d892c711..61283f928825 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/kmemcheck.h>
12#include <net/inet_hashtables.h> 13#include <net/inet_hashtables.h>
13#include <net/inet_timewait_sock.h> 14#include <net/inet_timewait_sock.h>
14#include <net/ip.h> 15#include <net/ip.h>
@@ -120,6 +121,8 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
120 if (tw != NULL) { 121 if (tw != NULL) {
121 const struct inet_sock *inet = inet_sk(sk); 122 const struct inet_sock *inet = inet_sk(sk);
122 123
124 kmemcheck_annotate_bitfield(tw, flags);
125
123 /* Give us an identity. */ 126 /* Give us an identity. */
124 tw->tw_daddr = inet->daddr; 127 tw->tw_daddr = inet->daddr;
125 tw->tw_rcv_saddr = inet->rcv_saddr; 128 tw->tw_rcv_saddr = inet->rcv_saddr;
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index a9b3a6f9ea95..656cbd195825 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -1,11 +1,12 @@
1/* 1/*
2 * linux/net/iucv/af_iucv.c
3 *
4 * IUCV protocol stack for Linux on zSeries 2 * IUCV protocol stack for Linux on zSeries
5 * 3 *
6 * Copyright 2006 IBM Corporation 4 * Copyright IBM Corp. 2006, 2009
7 * 5 *
8 * Author(s): Jennifer Hunt <jenhunt@us.ibm.com> 6 * Author(s): Jennifer Hunt <jenhunt@us.ibm.com>
7 * Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
8 * PM functions:
9 * Ursula Braun <ursula.braun@de.ibm.com>
9 */ 10 */
10 11
11#define KMSG_COMPONENT "af_iucv" 12#define KMSG_COMPONENT "af_iucv"
@@ -90,6 +91,122 @@ static inline void low_nmcpy(unsigned char *dst, char *src)
90 memcpy(&dst[8], src, 8); 91 memcpy(&dst[8], src, 8);
91} 92}
92 93
94static int afiucv_pm_prepare(struct device *dev)
95{
96#ifdef CONFIG_PM_DEBUG
97 printk(KERN_WARNING "afiucv_pm_prepare\n");
98#endif
99 return 0;
100}
101
102static void afiucv_pm_complete(struct device *dev)
103{
104#ifdef CONFIG_PM_DEBUG
105 printk(KERN_WARNING "afiucv_pm_complete\n");
106#endif
107 return;
108}
109
110/**
111 * afiucv_pm_freeze() - Freeze PM callback
112 * @dev: AFIUCV dummy device
113 *
114 * Sever all established IUCV communication pathes
115 */
116static int afiucv_pm_freeze(struct device *dev)
117{
118 struct iucv_sock *iucv;
119 struct sock *sk;
120 struct hlist_node *node;
121 int err = 0;
122
123#ifdef CONFIG_PM_DEBUG
124 printk(KERN_WARNING "afiucv_pm_freeze\n");
125#endif
126 read_lock(&iucv_sk_list.lock);
127 sk_for_each(sk, node, &iucv_sk_list.head) {
128 iucv = iucv_sk(sk);
129 skb_queue_purge(&iucv->send_skb_q);
130 skb_queue_purge(&iucv->backlog_skb_q);
131 switch (sk->sk_state) {
132 case IUCV_SEVERED:
133 case IUCV_DISCONN:
134 case IUCV_CLOSING:
135 case IUCV_CONNECTED:
136 if (iucv->path) {
137 err = iucv_path_sever(iucv->path, NULL);
138 iucv_path_free(iucv->path);
139 iucv->path = NULL;
140 }
141 break;
142 case IUCV_OPEN:
143 case IUCV_BOUND:
144 case IUCV_LISTEN:
145 case IUCV_CLOSED:
146 default:
147 break;
148 }
149 }
150 read_unlock(&iucv_sk_list.lock);
151 return err;
152}
153
154/**
155 * afiucv_pm_restore_thaw() - Thaw and restore PM callback
156 * @dev: AFIUCV dummy device
157 *
158 * socket clean up after freeze
159 */
160static int afiucv_pm_restore_thaw(struct device *dev)
161{
162 struct iucv_sock *iucv;
163 struct sock *sk;
164 struct hlist_node *node;
165
166#ifdef CONFIG_PM_DEBUG
167 printk(KERN_WARNING "afiucv_pm_restore_thaw\n");
168#endif
169 read_lock(&iucv_sk_list.lock);
170 sk_for_each(sk, node, &iucv_sk_list.head) {
171 iucv = iucv_sk(sk);
172 switch (sk->sk_state) {
173 case IUCV_CONNECTED:
174 sk->sk_err = EPIPE;
175 sk->sk_state = IUCV_DISCONN;
176 sk->sk_state_change(sk);
177 break;
178 case IUCV_DISCONN:
179 case IUCV_SEVERED:
180 case IUCV_CLOSING:
181 case IUCV_LISTEN:
182 case IUCV_BOUND:
183 case IUCV_OPEN:
184 default:
185 break;
186 }
187 }
188 read_unlock(&iucv_sk_list.lock);
189 return 0;
190}
191
192static struct dev_pm_ops afiucv_pm_ops = {
193 .prepare = afiucv_pm_prepare,
194 .complete = afiucv_pm_complete,
195 .freeze = afiucv_pm_freeze,
196 .thaw = afiucv_pm_restore_thaw,
197 .restore = afiucv_pm_restore_thaw,
198};
199
200static struct device_driver af_iucv_driver = {
201 .owner = THIS_MODULE,
202 .name = "afiucv",
203 .bus = &iucv_bus,
204 .pm = &afiucv_pm_ops,
205};
206
207/* dummy device used as trigger for PM functions */
208static struct device *af_iucv_dev;
209
93/** 210/**
94 * iucv_msg_length() - Returns the length of an iucv message. 211 * iucv_msg_length() - Returns the length of an iucv message.
95 * @msg: Pointer to struct iucv_message, MUST NOT be NULL 212 * @msg: Pointer to struct iucv_message, MUST NOT be NULL
@@ -1556,8 +1673,30 @@ static int __init afiucv_init(void)
1556 err = sock_register(&iucv_sock_family_ops); 1673 err = sock_register(&iucv_sock_family_ops);
1557 if (err) 1674 if (err)
1558 goto out_proto; 1675 goto out_proto;
1676 /* establish dummy device */
1677 err = driver_register(&af_iucv_driver);
1678 if (err)
1679 goto out_sock;
1680 af_iucv_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
1681 if (!af_iucv_dev) {
1682 err = -ENOMEM;
1683 goto out_driver;
1684 }
1685 dev_set_name(af_iucv_dev, "af_iucv");
1686 af_iucv_dev->bus = &iucv_bus;
1687 af_iucv_dev->parent = iucv_root;
1688 af_iucv_dev->release = (void (*)(struct device *))kfree;
1689 af_iucv_dev->driver = &af_iucv_driver;
1690 err = device_register(af_iucv_dev);
1691 if (err)
1692 goto out_driver;
1693
1559 return 0; 1694 return 0;
1560 1695
1696out_driver:
1697 driver_unregister(&af_iucv_driver);
1698out_sock:
1699 sock_unregister(PF_IUCV);
1561out_proto: 1700out_proto:
1562 proto_unregister(&iucv_proto); 1701 proto_unregister(&iucv_proto);
1563out_iucv: 1702out_iucv:
@@ -1568,6 +1707,8 @@ out:
1568 1707
1569static void __exit afiucv_exit(void) 1708static void __exit afiucv_exit(void)
1570{ 1709{
1710 device_unregister(af_iucv_dev);
1711 driver_unregister(&af_iucv_driver);
1571 sock_unregister(PF_IUCV); 1712 sock_unregister(PF_IUCV);
1572 proto_unregister(&iucv_proto); 1713 proto_unregister(&iucv_proto);
1573 iucv_unregister(&af_iucv_handler, 0); 1714 iucv_unregister(&af_iucv_handler, 0);
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 61e8038a55ee..c833481d32e3 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/*
@@ -364,6 +384,18 @@ static void iucv_allow_cpu(void *data)
364 parm->set_mask.ipmask = 0xf8; 384 parm->set_mask.ipmask = 0xf8;
365 iucv_call_b2f0(IUCV_SETMASK, parm); 385 iucv_call_b2f0(IUCV_SETMASK, parm);
366 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);
367 /* Set indication that iucv interrupts are allowed for this cpu. */ 399 /* Set indication that iucv interrupts are allowed for this cpu. */
368 cpu_set(cpu, iucv_irq_cpumask); 400 cpu_set(cpu, iucv_irq_cpumask);
369} 401}
@@ -389,6 +421,31 @@ static void iucv_block_cpu(void *data)
389} 421}
390 422
391/** 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/**
392 * iucv_declare_cpu 449 * iucv_declare_cpu
393 * @data: unused 450 * @data: unused
394 * 451 *
@@ -758,6 +815,28 @@ void iucv_unregister(struct iucv_handler *handler, int smp)
758} 815}
759EXPORT_SYMBOL(iucv_unregister); 816EXPORT_SYMBOL(iucv_unregister);
760 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
761/** 840/**
762 * iucv_path_accept 841 * iucv_path_accept
763 * @path: address of iucv path structure 842 * @path: address of iucv path structure
@@ -777,6 +856,10 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
777 int rc; 856 int rc;
778 857
779 local_bh_disable(); 858 local_bh_disable();
859 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
860 rc = -EIO;
861 goto out;
862 }
780 /* Prepare parameter block. */ 863 /* Prepare parameter block. */
781 parm = iucv_param[smp_processor_id()]; 864 parm = iucv_param[smp_processor_id()];
782 memset(parm, 0, sizeof(union iucv_param)); 865 memset(parm, 0, sizeof(union iucv_param));
@@ -792,6 +875,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
792 path->msglim = parm->ctrl.ipmsglim; 875 path->msglim = parm->ctrl.ipmsglim;
793 path->flags = parm->ctrl.ipflags1; 876 path->flags = parm->ctrl.ipflags1;
794 } 877 }
878out:
795 local_bh_enable(); 879 local_bh_enable();
796 return rc; 880 return rc;
797} 881}
@@ -821,6 +905,10 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
821 905
822 spin_lock_bh(&iucv_table_lock); 906 spin_lock_bh(&iucv_table_lock);
823 iucv_cleanup_queue(); 907 iucv_cleanup_queue();
908 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
909 rc = -EIO;
910 goto out;
911 }
824 parm = iucv_param[smp_processor_id()]; 912 parm = iucv_param[smp_processor_id()];
825 memset(parm, 0, sizeof(union iucv_param)); 913 memset(parm, 0, sizeof(union iucv_param));
826 parm->ctrl.ipmsglim = path->msglim; 914 parm->ctrl.ipmsglim = path->msglim;
@@ -855,6 +943,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
855 rc = -EIO; 943 rc = -EIO;
856 } 944 }
857 } 945 }
946out:
858 spin_unlock_bh(&iucv_table_lock); 947 spin_unlock_bh(&iucv_table_lock);
859 return rc; 948 return rc;
860} 949}
@@ -876,12 +965,17 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16])
876 int rc; 965 int rc;
877 966
878 local_bh_disable(); 967 local_bh_disable();
968 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
969 rc = -EIO;
970 goto out;
971 }
879 parm = iucv_param[smp_processor_id()]; 972 parm = iucv_param[smp_processor_id()];
880 memset(parm, 0, sizeof(union iucv_param)); 973 memset(parm, 0, sizeof(union iucv_param));
881 if (userdata) 974 if (userdata)
882 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); 975 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
883 parm->ctrl.ippathid = path->pathid; 976 parm->ctrl.ippathid = path->pathid;
884 rc = iucv_call_b2f0(IUCV_QUIESCE, parm); 977 rc = iucv_call_b2f0(IUCV_QUIESCE, parm);
978out:
885 local_bh_enable(); 979 local_bh_enable();
886 return rc; 980 return rc;
887} 981}
@@ -903,12 +997,17 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16])
903 int rc; 997 int rc;
904 998
905 local_bh_disable(); 999 local_bh_disable();
1000 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1001 rc = -EIO;
1002 goto out;
1003 }
906 parm = iucv_param[smp_processor_id()]; 1004 parm = iucv_param[smp_processor_id()];
907 memset(parm, 0, sizeof(union iucv_param)); 1005 memset(parm, 0, sizeof(union iucv_param));
908 if (userdata) 1006 if (userdata)
909 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); 1007 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
910 parm->ctrl.ippathid = path->pathid; 1008 parm->ctrl.ippathid = path->pathid;
911 rc = iucv_call_b2f0(IUCV_RESUME, parm); 1009 rc = iucv_call_b2f0(IUCV_RESUME, parm);
1010out:
912 local_bh_enable(); 1011 local_bh_enable();
913 return rc; 1012 return rc;
914} 1013}
@@ -927,6 +1026,10 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
927 int rc; 1026 int rc;
928 1027
929 preempt_disable(); 1028 preempt_disable();
1029 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1030 rc = -EIO;
1031 goto out;
1032 }
930 if (iucv_active_cpu != smp_processor_id()) 1033 if (iucv_active_cpu != smp_processor_id())
931 spin_lock_bh(&iucv_table_lock); 1034 spin_lock_bh(&iucv_table_lock);
932 rc = iucv_sever_pathid(path->pathid, userdata); 1035 rc = iucv_sever_pathid(path->pathid, userdata);
@@ -934,6 +1037,7 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
934 list_del_init(&path->list); 1037 list_del_init(&path->list);
935 if (iucv_active_cpu != smp_processor_id()) 1038 if (iucv_active_cpu != smp_processor_id())
936 spin_unlock_bh(&iucv_table_lock); 1039 spin_unlock_bh(&iucv_table_lock);
1040out:
937 preempt_enable(); 1041 preempt_enable();
938 return rc; 1042 return rc;
939} 1043}
@@ -956,6 +1060,10 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
956 int rc; 1060 int rc;
957 1061
958 local_bh_disable(); 1062 local_bh_disable();
1063 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1064 rc = -EIO;
1065 goto out;
1066 }
959 parm = iucv_param[smp_processor_id()]; 1067 parm = iucv_param[smp_processor_id()];
960 memset(parm, 0, sizeof(union iucv_param)); 1068 memset(parm, 0, sizeof(union iucv_param));
961 parm->purge.ippathid = path->pathid; 1069 parm->purge.ippathid = path->pathid;
@@ -967,6 +1075,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
967 msg->audit = (*(u32 *) &parm->purge.ipaudit) >> 8; 1075 msg->audit = (*(u32 *) &parm->purge.ipaudit) >> 8;
968 msg->tag = parm->purge.ipmsgtag; 1076 msg->tag = parm->purge.ipmsgtag;
969 } 1077 }
1078out:
970 local_bh_enable(); 1079 local_bh_enable();
971 return rc; 1080 return rc;
972} 1081}
@@ -1043,6 +1152,10 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
1043 if (msg->flags & IUCV_IPRMDATA) 1152 if (msg->flags & IUCV_IPRMDATA)
1044 return iucv_message_receive_iprmdata(path, msg, flags, 1153 return iucv_message_receive_iprmdata(path, msg, flags,
1045 buffer, size, residual); 1154 buffer, size, residual);
1155 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1156 rc = -EIO;
1157 goto out;
1158 }
1046 parm = iucv_param[smp_processor_id()]; 1159 parm = iucv_param[smp_processor_id()];
1047 memset(parm, 0, sizeof(union iucv_param)); 1160 memset(parm, 0, sizeof(union iucv_param));
1048 parm->db.ipbfadr1 = (u32)(addr_t) buffer; 1161 parm->db.ipbfadr1 = (u32)(addr_t) buffer;
@@ -1058,6 +1171,7 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
1058 if (residual) 1171 if (residual)
1059 *residual = parm->db.ipbfln1f; 1172 *residual = parm->db.ipbfln1f;
1060 } 1173 }
1174out:
1061 return rc; 1175 return rc;
1062} 1176}
1063EXPORT_SYMBOL(__iucv_message_receive); 1177EXPORT_SYMBOL(__iucv_message_receive);
@@ -1111,6 +1225,10 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
1111 int rc; 1225 int rc;
1112 1226
1113 local_bh_disable(); 1227 local_bh_disable();
1228 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1229 rc = -EIO;
1230 goto out;
1231 }
1114 parm = iucv_param[smp_processor_id()]; 1232 parm = iucv_param[smp_processor_id()];
1115 memset(parm, 0, sizeof(union iucv_param)); 1233 memset(parm, 0, sizeof(union iucv_param));
1116 parm->db.ippathid = path->pathid; 1234 parm->db.ippathid = path->pathid;
@@ -1118,6 +1236,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
1118 parm->db.iptrgcls = msg->class; 1236 parm->db.iptrgcls = msg->class;
1119 parm->db.ipflags1 = (IUCV_IPTRGCLS | IUCV_IPFGMID | IUCV_IPFGPID); 1237 parm->db.ipflags1 = (IUCV_IPTRGCLS | IUCV_IPFGMID | IUCV_IPFGPID);
1120 rc = iucv_call_b2f0(IUCV_REJECT, parm); 1238 rc = iucv_call_b2f0(IUCV_REJECT, parm);
1239out:
1121 local_bh_enable(); 1240 local_bh_enable();
1122 return rc; 1241 return rc;
1123} 1242}
@@ -1145,6 +1264,10 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
1145 int rc; 1264 int rc;
1146 1265
1147 local_bh_disable(); 1266 local_bh_disable();
1267 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1268 rc = -EIO;
1269 goto out;
1270 }
1148 parm = iucv_param[smp_processor_id()]; 1271 parm = iucv_param[smp_processor_id()];
1149 memset(parm, 0, sizeof(union iucv_param)); 1272 memset(parm, 0, sizeof(union iucv_param));
1150 if (flags & IUCV_IPRMDATA) { 1273 if (flags & IUCV_IPRMDATA) {
@@ -1162,6 +1285,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
1162 parm->db.iptrgcls = msg->class; 1285 parm->db.iptrgcls = msg->class;
1163 } 1286 }
1164 rc = iucv_call_b2f0(IUCV_REPLY, parm); 1287 rc = iucv_call_b2f0(IUCV_REPLY, parm);
1288out:
1165 local_bh_enable(); 1289 local_bh_enable();
1166 return rc; 1290 return rc;
1167} 1291}
@@ -1190,6 +1314,10 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
1190 union iucv_param *parm; 1314 union iucv_param *parm;
1191 int rc; 1315 int rc;
1192 1316
1317 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1318 rc = -EIO;
1319 goto out;
1320 }
1193 parm = iucv_param[smp_processor_id()]; 1321 parm = iucv_param[smp_processor_id()];
1194 memset(parm, 0, sizeof(union iucv_param)); 1322 memset(parm, 0, sizeof(union iucv_param));
1195 if (flags & IUCV_IPRMDATA) { 1323 if (flags & IUCV_IPRMDATA) {
@@ -1212,6 +1340,7 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
1212 rc = iucv_call_b2f0(IUCV_SEND, parm); 1340 rc = iucv_call_b2f0(IUCV_SEND, parm);
1213 if (!rc) 1341 if (!rc)
1214 msg->id = parm->db.ipmsgid; 1342 msg->id = parm->db.ipmsgid;
1343out:
1215 return rc; 1344 return rc;
1216} 1345}
1217EXPORT_SYMBOL(__iucv_message_send); 1346EXPORT_SYMBOL(__iucv_message_send);
@@ -1272,6 +1401,10 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
1272 int rc; 1401 int rc;
1273 1402
1274 local_bh_disable(); 1403 local_bh_disable();
1404 if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) {
1405 rc = -EIO;
1406 goto out;
1407 }
1275 parm = iucv_param[smp_processor_id()]; 1408 parm = iucv_param[smp_processor_id()];
1276 memset(parm, 0, sizeof(union iucv_param)); 1409 memset(parm, 0, sizeof(union iucv_param));
1277 if (flags & IUCV_IPRMDATA) { 1410 if (flags & IUCV_IPRMDATA) {
@@ -1297,6 +1430,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
1297 rc = iucv_call_b2f0(IUCV_SEND, parm); 1430 rc = iucv_call_b2f0(IUCV_SEND, parm);
1298 if (!rc) 1431 if (!rc)
1299 msg->id = parm->db.ipmsgid; 1432 msg->id = parm->db.ipmsgid;
1433out:
1300 local_bh_enable(); 1434 local_bh_enable();
1301 return rc; 1435 return rc;
1302} 1436}
@@ -1687,6 +1821,130 @@ static void iucv_external_interrupt(u16 code)
1687 spin_unlock(&iucv_queue_lock); 1821 spin_unlock(&iucv_queue_lock);
1688} 1822}
1689 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
1690/** 1948/**
1691 * iucv_init 1949 * iucv_init
1692 * 1950 *
@@ -1740,15 +1998,20 @@ static int __init iucv_init(void)
1740 rc = register_hotcpu_notifier(&iucv_cpu_notifier); 1998 rc = register_hotcpu_notifier(&iucv_cpu_notifier);
1741 if (rc) 1999 if (rc)
1742 goto out_free; 2000 goto out_free;
2001 rc = register_reboot_notifier(&iucv_reboot_notifier);
2002 if (rc)
2003 goto out_cpu;
1743 ASCEBC(iucv_error_no_listener, 16); 2004 ASCEBC(iucv_error_no_listener, 16);
1744 ASCEBC(iucv_error_no_memory, 16); 2005 ASCEBC(iucv_error_no_memory, 16);
1745 ASCEBC(iucv_error_pathid, 16); 2006 ASCEBC(iucv_error_pathid, 16);
1746 iucv_available = 1; 2007 iucv_available = 1;
1747 rc = bus_register(&iucv_bus); 2008 rc = bus_register(&iucv_bus);
1748 if (rc) 2009 if (rc)
1749 goto out_cpu; 2010 goto out_reboot;
1750 return 0; 2011 return 0;
1751 2012
2013out_reboot:
2014 unregister_reboot_notifier(&iucv_reboot_notifier);
1752out_cpu: 2015out_cpu:
1753 unregister_hotcpu_notifier(&iucv_cpu_notifier); 2016 unregister_hotcpu_notifier(&iucv_cpu_notifier);
1754out_free: 2017out_free:
@@ -1783,6 +2046,7 @@ static void __exit iucv_exit(void)
1783 list_for_each_entry_safe(p, n, &iucv_work_queue, list) 2046 list_for_each_entry_safe(p, n, &iucv_work_queue, list)
1784 kfree(p); 2047 kfree(p);
1785 spin_unlock_irq(&iucv_queue_lock); 2048 spin_unlock_irq(&iucv_queue_lock);
2049 unregister_reboot_notifier(&iucv_reboot_notifier);
1786 unregister_hotcpu_notifier(&iucv_cpu_notifier); 2050 unregister_hotcpu_notifier(&iucv_cpu_notifier);
1787 for_each_possible_cpu(cpu) { 2051 for_each_possible_cpu(cpu) {
1788 kfree(iucv_param_irq[cpu]); 2052 kfree(iucv_param_irq[cpu]);