]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.arch/s390-10-08-iucv-2ndparm.patch
Merge branch 'master' into next
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.arch / s390-10-08-iucv-2ndparm.patch
1 From: Gerald Schaefer <geraldsc@de.ibm.com>
2 Subject: iucv: provide second per-cpu IUCV command parameter block
3 References: bnc#482818,LTC#52502
4
5 Symptom: failing connect during cpu hotplugging
6 Problem: Some of the IUCV commands can be invoked in interrupt
7 context. If they use the same per-cpu IUCV command
8 parameter block as another IUCV command invoked in
9 process context and running in parallel, the IUCV command
10 parameter of the not yet finished IUCV command invocation
11 in process context might be overwritten.
12 Solution: Provide a different per-cpu IUCV command parameter block
13 for IUCV commands that can be invoked in interrupt
14 context.
15
16 Acked-by: John Jolly <jjolly@suse.de>
17 ---
18
19 net/iucv/iucv.c | 41 +++++++++++++++++++++++++++++++----------
20 1 file changed, 31 insertions(+), 10 deletions(-)
21
22 Index: linux-sles11/net/iucv/iucv.c
23 ===================================================================
24 --- linux-sles11.orig/net/iucv/iucv.c
25 +++ linux-sles11/net/iucv/iucv.c
26 @@ -280,6 +280,7 @@ union iucv_param {
27 * Anchor for per-cpu IUCV command parameter block.
28 */
29 static union iucv_param *iucv_param[NR_CPUS];
30 +static union iucv_param *iucv_param_irq[NR_CPUS];
31
32 /**
33 * iucv_call_b2f0
34 @@ -358,7 +359,7 @@ static void iucv_allow_cpu(void *data)
35 * 0x10 - Flag to allow priority message completion interrupts
36 * 0x08 - Flag to allow IUCV control interrupts
37 */
38 - parm = iucv_param[cpu];
39 + parm = iucv_param_irq[cpu];
40 memset(parm, 0, sizeof(union iucv_param));
41 parm->set_mask.ipmask = 0xf8;
42 iucv_call_b2f0(IUCV_SETMASK, parm);
43 @@ -379,7 +380,7 @@ static void iucv_block_cpu(void *data)
44 union iucv_param *parm;
45
46 /* Disable all iucv interrupts. */
47 - parm = iucv_param[cpu];
48 + parm = iucv_param_irq[cpu];
49 memset(parm, 0, sizeof(union iucv_param));
50 iucv_call_b2f0(IUCV_SETMASK, parm);
51
52 @@ -403,7 +404,7 @@ static void iucv_declare_cpu(void *data)
53 return;
54
55 /* Declare interrupt buffer. */
56 - parm = iucv_param[cpu];
57 + parm = iucv_param_irq[cpu];
58 memset(parm, 0, sizeof(union iucv_param));
59 parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]);
60 rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm);
61 @@ -460,7 +461,7 @@ static void iucv_retrieve_cpu(void *data
62 iucv_block_cpu(NULL);
63
64 /* Retrieve interrupt buffer. */
65 - parm = iucv_param[cpu];
66 + parm = iucv_param_irq[cpu];
67 iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm);
68
69 /* Clear indication that an iucv buffer exists for this cpu. */
70 @@ -574,11 +575,22 @@ static int __cpuinit iucv_cpu_notify(str
71 iucv_irq_data[cpu] = NULL;
72 return NOTIFY_BAD;
73 }
74 + iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
75 + GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
76 + if (!iucv_param_irq[cpu]) {
77 + kfree(iucv_param[cpu]);
78 + iucv_param[cpu] = NULL;
79 + kfree(iucv_irq_data[cpu]);
80 + iucv_irq_data[cpu] = NULL;
81 + return NOTIFY_BAD;
82 + }
83 break;
84 case CPU_UP_CANCELED:
85 case CPU_UP_CANCELED_FROZEN:
86 case CPU_DEAD:
87 case CPU_DEAD_FROZEN:
88 + kfree(iucv_param_irq[cpu]);
89 + iucv_param_irq[cpu] = NULL;
90 kfree(iucv_param[cpu]);
91 iucv_param[cpu] = NULL;
92 kfree(iucv_irq_data[cpu]);
93 @@ -625,7 +637,7 @@ static int iucv_sever_pathid(u16 pathid,
94 {
95 union iucv_param *parm;
96
97 - parm = iucv_param[smp_processor_id()];
98 + parm = iucv_param_irq[smp_processor_id()];
99 memset(parm, 0, sizeof(union iucv_param));
100 if (userdata)
101 memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
102 @@ -918,10 +930,8 @@ int iucv_path_sever(struct iucv_path *pa
103 if (iucv_active_cpu != smp_processor_id())
104 spin_lock_bh(&iucv_table_lock);
105 rc = iucv_sever_pathid(path->pathid, userdata);
106 - if (!rc) {
107 - iucv_path_table[path->pathid] = NULL;
108 - list_del_init(&path->list);
109 - }
110 + iucv_path_table[path->pathid] = NULL;
111 + list_del_init(&path->list);
112 if (iucv_active_cpu != smp_processor_id())
113 spin_unlock_bh(&iucv_table_lock);
114 preempt_enable();
115 @@ -1333,7 +1343,7 @@ static void iucv_path_severed(struct iuc
116 else {
117 iucv_sever_pathid(path->pathid, NULL);
118 iucv_path_table[path->pathid] = NULL;
119 - list_del_init(&path->list);
120 + list_del(&path->list);
121 iucv_path_free(path);
122 }
123 }
124 @@ -1637,6 +1647,13 @@ static int __init iucv_init(void)
125 rc = -ENOMEM;
126 goto out_free;
127 }
128 + iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
129 + GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
130 + if (!iucv_param_irq[cpu]) {
131 + rc = -ENOMEM;
132 + goto out_free;
133 + }
134 +
135 }
136 rc = register_hotcpu_notifier(&iucv_cpu_notifier);
137 if (rc)
138 @@ -1654,6 +1671,8 @@ out_cpu:
139 unregister_hotcpu_notifier(&iucv_cpu_notifier);
140 out_free:
141 for_each_possible_cpu(cpu) {
142 + kfree(iucv_param_irq[cpu]);
143 + iucv_param_irq[cpu] = NULL;
144 kfree(iucv_param[cpu]);
145 iucv_param[cpu] = NULL;
146 kfree(iucv_irq_data[cpu]);
147 @@ -1684,6 +1703,8 @@ static void __exit iucv_exit(void)
148 spin_unlock_irq(&iucv_queue_lock);
149 unregister_hotcpu_notifier(&iucv_cpu_notifier);
150 for_each_possible_cpu(cpu) {
151 + kfree(iucv_param_irq[cpu]);
152 + iucv_param_irq[cpu] = NULL;
153 kfree(iucv_param[cpu]);
154 iucv_param[cpu] = NULL;
155 kfree(iucv_irq_data[cpu]);