Commit 42e1b4c2 authored by Ursula Braun's avatar Ursula Braun Committed by David S. Miller

iucv: provide second per-cpu IUCV command parameter block

Some of the IUCV commands can be invoked in interrupt context.
Those commands need a different per-cpu IUCV command parameter block,
otherwise they might overwrite an IUCV command parameter of a not yet
finished IUCV command invocation in process context.
Signed-off-by: default avatarUrsula Braun <ursula.braun@de.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 362b76ed
...@@ -280,6 +280,7 @@ union iucv_param { ...@@ -280,6 +280,7 @@ union iucv_param {
* Anchor for per-cpu IUCV command parameter block. * Anchor for per-cpu IUCV command parameter block.
*/ */
static union iucv_param *iucv_param[NR_CPUS]; static union iucv_param *iucv_param[NR_CPUS];
static union iucv_param *iucv_param_irq[NR_CPUS];
/** /**
* iucv_call_b2f0 * iucv_call_b2f0
...@@ -358,7 +359,7 @@ static void iucv_allow_cpu(void *data) ...@@ -358,7 +359,7 @@ static void iucv_allow_cpu(void *data)
* 0x10 - Flag to allow priority message completion interrupts * 0x10 - Flag to allow priority message completion interrupts
* 0x08 - Flag to allow IUCV control interrupts * 0x08 - Flag to allow IUCV control interrupts
*/ */
parm = iucv_param[cpu]; parm = iucv_param_irq[cpu];
memset(parm, 0, sizeof(union iucv_param)); memset(parm, 0, sizeof(union iucv_param));
parm->set_mask.ipmask = 0xf8; parm->set_mask.ipmask = 0xf8;
iucv_call_b2f0(IUCV_SETMASK, parm); iucv_call_b2f0(IUCV_SETMASK, parm);
...@@ -379,7 +380,7 @@ static void iucv_block_cpu(void *data) ...@@ -379,7 +380,7 @@ static void iucv_block_cpu(void *data)
union iucv_param *parm; union iucv_param *parm;
/* Disable all iucv interrupts. */ /* Disable all iucv interrupts. */
parm = iucv_param[cpu]; parm = iucv_param_irq[cpu];
memset(parm, 0, sizeof(union iucv_param)); memset(parm, 0, sizeof(union iucv_param));
iucv_call_b2f0(IUCV_SETMASK, parm); iucv_call_b2f0(IUCV_SETMASK, parm);
...@@ -403,7 +404,7 @@ static void iucv_declare_cpu(void *data) ...@@ -403,7 +404,7 @@ static void iucv_declare_cpu(void *data)
return; return;
/* Declare interrupt buffer. */ /* Declare interrupt buffer. */
parm = iucv_param[cpu]; parm = iucv_param_irq[cpu];
memset(parm, 0, sizeof(union iucv_param)); memset(parm, 0, sizeof(union iucv_param));
parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]); parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]);
rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm); rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm);
...@@ -460,7 +461,7 @@ static void iucv_retrieve_cpu(void *data) ...@@ -460,7 +461,7 @@ static void iucv_retrieve_cpu(void *data)
iucv_block_cpu(NULL); iucv_block_cpu(NULL);
/* Retrieve interrupt buffer. */ /* Retrieve interrupt buffer. */
parm = iucv_param[cpu]; parm = iucv_param_irq[cpu];
iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm); iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm);
/* Clear indication that an iucv buffer exists for this cpu. */ /* Clear indication that an iucv buffer exists for this cpu. */
...@@ -574,11 +575,22 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self, ...@@ -574,11 +575,22 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
iucv_irq_data[cpu] = NULL; iucv_irq_data[cpu] = NULL;
return NOTIFY_BAD; return NOTIFY_BAD;
} }
iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
if (!iucv_param_irq[cpu]) {
kfree(iucv_param[cpu]);
iucv_param[cpu] = NULL;
kfree(iucv_irq_data[cpu]);
iucv_irq_data[cpu] = NULL;
return NOTIFY_BAD;
}
break; break;
case CPU_UP_CANCELED: case CPU_UP_CANCELED:
case CPU_UP_CANCELED_FROZEN: case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD: case CPU_DEAD:
case CPU_DEAD_FROZEN: case CPU_DEAD_FROZEN:
kfree(iucv_param_irq[cpu]);
iucv_param_irq[cpu] = NULL;
kfree(iucv_param[cpu]); kfree(iucv_param[cpu]);
iucv_param[cpu] = NULL; iucv_param[cpu] = NULL;
kfree(iucv_irq_data[cpu]); kfree(iucv_irq_data[cpu]);
...@@ -625,7 +637,7 @@ static int iucv_sever_pathid(u16 pathid, u8 userdata[16]) ...@@ -625,7 +637,7 @@ static int iucv_sever_pathid(u16 pathid, u8 userdata[16])
{ {
union iucv_param *parm; union iucv_param *parm;
parm = iucv_param[smp_processor_id()]; parm = iucv_param_irq[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param)); memset(parm, 0, sizeof(union iucv_param));
if (userdata) if (userdata)
memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
...@@ -918,10 +930,8 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16]) ...@@ -918,10 +930,8 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
if (iucv_active_cpu != smp_processor_id()) if (iucv_active_cpu != smp_processor_id())
spin_lock_bh(&iucv_table_lock); spin_lock_bh(&iucv_table_lock);
rc = iucv_sever_pathid(path->pathid, userdata); rc = iucv_sever_pathid(path->pathid, userdata);
if (!rc) { iucv_path_table[path->pathid] = NULL;
iucv_path_table[path->pathid] = NULL; list_del_init(&path->list);
list_del_init(&path->list);
}
if (iucv_active_cpu != smp_processor_id()) if (iucv_active_cpu != smp_processor_id())
spin_unlock_bh(&iucv_table_lock); spin_unlock_bh(&iucv_table_lock);
preempt_enable(); preempt_enable();
...@@ -1413,7 +1423,7 @@ static void iucv_path_severed(struct iucv_irq_data *data) ...@@ -1413,7 +1423,7 @@ static void iucv_path_severed(struct iucv_irq_data *data)
else { else {
iucv_sever_pathid(path->pathid, NULL); iucv_sever_pathid(path->pathid, NULL);
iucv_path_table[path->pathid] = NULL; iucv_path_table[path->pathid] = NULL;
list_del_init(&path->list); list_del(&path->list);
iucv_path_free(path); iucv_path_free(path);
} }
} }
...@@ -1717,6 +1727,13 @@ static int __init iucv_init(void) ...@@ -1717,6 +1727,13 @@ static int __init iucv_init(void)
rc = -ENOMEM; rc = -ENOMEM;
goto out_free; goto out_free;
} }
iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
if (!iucv_param_irq[cpu]) {
rc = -ENOMEM;
goto out_free;
}
} }
rc = register_hotcpu_notifier(&iucv_cpu_notifier); rc = register_hotcpu_notifier(&iucv_cpu_notifier);
if (rc) if (rc)
...@@ -1734,6 +1751,8 @@ static int __init iucv_init(void) ...@@ -1734,6 +1751,8 @@ static int __init iucv_init(void)
unregister_hotcpu_notifier(&iucv_cpu_notifier); unregister_hotcpu_notifier(&iucv_cpu_notifier);
out_free: out_free:
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
kfree(iucv_param_irq[cpu]);
iucv_param_irq[cpu] = NULL;
kfree(iucv_param[cpu]); kfree(iucv_param[cpu]);
iucv_param[cpu] = NULL; iucv_param[cpu] = NULL;
kfree(iucv_irq_data[cpu]); kfree(iucv_irq_data[cpu]);
...@@ -1764,6 +1783,8 @@ static void __exit iucv_exit(void) ...@@ -1764,6 +1783,8 @@ static void __exit iucv_exit(void)
spin_unlock_irq(&iucv_queue_lock); spin_unlock_irq(&iucv_queue_lock);
unregister_hotcpu_notifier(&iucv_cpu_notifier); unregister_hotcpu_notifier(&iucv_cpu_notifier);
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
kfree(iucv_param_irq[cpu]);
iucv_param_irq[cpu] = NULL;
kfree(iucv_param[cpu]); kfree(iucv_param[cpu]);
iucv_param[cpu] = NULL; iucv_param[cpu] = NULL;
kfree(iucv_irq_data[cpu]); kfree(iucv_irq_data[cpu]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment