]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/iucv/iucv.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[karo-tx-linux.git] / net / iucv / iucv.c
index 8f57d4f4328a88265792a881f99dfd92ca077f15..61e8038a55ee300d3875ffcf01532624bc691dd6 100644 (file)
@@ -50,7 +50,6 @@
 #include <asm/ebcdic.h>
 #include <asm/io.h>
 #include <asm/s390_ext.h>
-#include <asm/s390_rdev.h>
 #include <asm/smp.h>
 
 /*
@@ -281,6 +280,7 @@ union iucv_param {
  * Anchor for per-cpu IUCV command parameter block.
  */
 static union iucv_param *iucv_param[NR_CPUS];
+static union iucv_param *iucv_param_irq[NR_CPUS];
 
 /**
  * iucv_call_b2f0
@@ -359,7 +359,7 @@ static void iucv_allow_cpu(void *data)
         *      0x10 - Flag to allow priority message completion interrupts
         *      0x08 - Flag to allow IUCV control interrupts
         */
-       parm = iucv_param[cpu];
+       parm = iucv_param_irq[cpu];
        memset(parm, 0, sizeof(union iucv_param));
        parm->set_mask.ipmask = 0xf8;
        iucv_call_b2f0(IUCV_SETMASK, parm);
@@ -380,7 +380,7 @@ static void iucv_block_cpu(void *data)
        union iucv_param *parm;
 
        /* Disable all iucv interrupts. */
-       parm = iucv_param[cpu];
+       parm = iucv_param_irq[cpu];
        memset(parm, 0, sizeof(union iucv_param));
        iucv_call_b2f0(IUCV_SETMASK, parm);
 
@@ -404,7 +404,7 @@ static void iucv_declare_cpu(void *data)
                return;
 
        /* Declare interrupt buffer. */
-       parm = iucv_param[cpu];
+       parm = iucv_param_irq[cpu];
        memset(parm, 0, sizeof(union iucv_param));
        parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]);
        rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm);
@@ -461,7 +461,7 @@ static void iucv_retrieve_cpu(void *data)
        iucv_block_cpu(NULL);
 
        /* Retrieve interrupt buffer. */
-       parm = iucv_param[cpu];
+       parm = iucv_param_irq[cpu];
        iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm);
 
        /* Clear indication that an iucv buffer exists for this cpu. */
@@ -517,6 +517,7 @@ static int iucv_enable(void)
        size_t alloc_size;
        int cpu, rc;
 
+       get_online_cpus();
        rc = -ENOMEM;
        alloc_size = iucv_max_pathid * sizeof(struct iucv_path);
        iucv_path_table = kzalloc(alloc_size, GFP_KERNEL);
@@ -524,19 +525,17 @@ static int iucv_enable(void)
                goto out;
        /* Declare per cpu buffers. */
        rc = -EIO;
-       get_online_cpus();
        for_each_online_cpu(cpu)
                smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
        if (cpus_empty(iucv_buffer_cpumask))
                /* No cpu could declare an iucv buffer. */
-               goto out_path;
+               goto out;
        put_online_cpus();
        return 0;
-
-out_path:
-       put_online_cpus();
-       kfree(iucv_path_table);
 out:
+       kfree(iucv_path_table);
+       iucv_path_table = NULL;
+       put_online_cpus();
        return rc;
 }
 
@@ -551,8 +550,9 @@ static void iucv_disable(void)
 {
        get_online_cpus();
        on_each_cpu(iucv_retrieve_cpu, NULL, 1);
-       put_online_cpus();
        kfree(iucv_path_table);
+       iucv_path_table = NULL;
+       put_online_cpus();
 }
 
 static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
@@ -575,11 +575,22 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
                        iucv_irq_data[cpu] = NULL;
                        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;
        case CPU_UP_CANCELED:
        case CPU_UP_CANCELED_FROZEN:
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
+               kfree(iucv_param_irq[cpu]);
+               iucv_param_irq[cpu] = NULL;
                kfree(iucv_param[cpu]);
                iucv_param[cpu] = NULL;
                kfree(iucv_irq_data[cpu]);
@@ -589,10 +600,14 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
        case CPU_ONLINE_FROZEN:
        case CPU_DOWN_FAILED:
        case CPU_DOWN_FAILED_FROZEN:
+               if (!iucv_path_table)
+                       break;
                smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
                break;
        case CPU_DOWN_PREPARE:
        case CPU_DOWN_PREPARE_FROZEN:
+               if (!iucv_path_table)
+                       break;
                cpumask = iucv_buffer_cpumask;
                cpu_clear(cpu, cpumask);
                if (cpus_empty(cpumask))
@@ -622,7 +637,7 @@ static int iucv_sever_pathid(u16 pathid, u8 userdata[16])
 {
        union iucv_param *parm;
 
-       parm = iucv_param[smp_processor_id()];
+       parm = iucv_param_irq[smp_processor_id()];
        memset(parm, 0, sizeof(union iucv_param));
        if (userdata)
                memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
@@ -915,10 +930,8 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
        if (iucv_active_cpu != smp_processor_id())
                spin_lock_bh(&iucv_table_lock);
        rc = iucv_sever_pathid(path->pathid, userdata);
-       if (!rc) {
-               iucv_path_table[path->pathid] = NULL;
-               list_del_init(&path->list);
-       }
+       iucv_path_table[path->pathid] = NULL;
+       list_del_init(&path->list);
        if (iucv_active_cpu != smp_processor_id())
                spin_unlock_bh(&iucv_table_lock);
        preempt_enable();
@@ -1375,6 +1388,8 @@ static void iucv_path_complete(struct iucv_irq_data *data)
        struct iucv_path_complete *ipc = (void *) data;
        struct iucv_path *path = iucv_path_table[ipc->ippathid];
 
+       if (path)
+               path->flags = ipc->ipflags1;
        if (path && path->handler && path->handler->path_complete)
                path->handler->path_complete(path, ipc->ipuser);
 }
@@ -1410,7 +1425,7 @@ static void iucv_path_severed(struct iucv_irq_data *data)
        else {
                iucv_sever_pathid(path->pathid, NULL);
                iucv_path_table[path->pathid] = NULL;
-               list_del_init(&path->list);
+               list_del(&path->list);
                iucv_path_free(path);
        }
 }
@@ -1692,7 +1707,7 @@ static int __init iucv_init(void)
        rc = register_external_interrupt(0x4000, iucv_external_interrupt);
        if (rc)
                goto out;
-       iucv_root = s390_root_dev_register("iucv");
+       iucv_root = root_device_register("iucv");
        if (IS_ERR(iucv_root)) {
                rc = PTR_ERR(iucv_root);
                goto out_int;
@@ -1714,6 +1729,13 @@ static int __init iucv_init(void)
                        rc = -ENOMEM;
                        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);
        if (rc)
@@ -1731,12 +1753,14 @@ out_cpu:
        unregister_hotcpu_notifier(&iucv_cpu_notifier);
 out_free:
        for_each_possible_cpu(cpu) {
+               kfree(iucv_param_irq[cpu]);
+               iucv_param_irq[cpu] = NULL;
                kfree(iucv_param[cpu]);
                iucv_param[cpu] = NULL;
                kfree(iucv_irq_data[cpu]);
                iucv_irq_data[cpu] = NULL;
        }
-       s390_root_dev_unregister(iucv_root);
+       root_device_unregister(iucv_root);
 out_int:
        unregister_external_interrupt(0x4000, iucv_external_interrupt);
 out:
@@ -1761,12 +1785,14 @@ static void __exit iucv_exit(void)
        spin_unlock_irq(&iucv_queue_lock);
        unregister_hotcpu_notifier(&iucv_cpu_notifier);
        for_each_possible_cpu(cpu) {
+               kfree(iucv_param_irq[cpu]);
+               iucv_param_irq[cpu] = NULL;
                kfree(iucv_param[cpu]);
                iucv_param[cpu] = NULL;
                kfree(iucv_irq_data[cpu]);
                iucv_irq_data[cpu] = NULL;
        }
-       s390_root_dev_unregister(iucv_root);
+       root_device_unregister(iucv_root);
        bus_unregister(&iucv_bus);
        unregister_external_interrupt(0x4000, iucv_external_interrupt);
 }