arm/xen: Initialize event channels earlier
[firefly-linux-kernel-4.4.55.git] / arch / arm / xen / enlighten.c
index 85501238b4258316272f9448ad8829b18a1111b2..3465f25d77020d7b49cb93b4821795abe966a64f 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/of_address.h>
 #include <linux/cpuidle.h>
 #include <linux/cpufreq.h>
+#include <linux/cpu.h>
 
 #include <linux/mm.h>
 
@@ -154,7 +155,7 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
 }
 EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
 
-static void __init xen_percpu_init(void *unused)
+static void xen_percpu_init(void)
 {
        struct vcpu_register_vcpu_info info;
        struct vcpu_info *vcpup;
@@ -193,6 +194,31 @@ static void xen_power_off(void)
                BUG();
 }
 
+static int xen_cpu_notification(struct notifier_block *self,
+                               unsigned long action,
+                               void *hcpu)
+{
+       switch (action) {
+       case CPU_STARTING:
+               xen_percpu_init();
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block xen_cpu_notifier = {
+       .notifier_call = xen_cpu_notification,
+};
+
+static irqreturn_t xen_arm_callback(int irq, void *arg)
+{
+       xen_hvm_evtchn_do_upcall();
+       return IRQ_HANDLED;
+}
+
 /*
  * see Documentation/devicetree/bindings/arm/xen.txt for the
  * documentation of the Xen Device Tree format.
@@ -208,6 +234,7 @@ static int __init xen_guest_init(void)
        const char *version = NULL;
        const char *xen_prefix = "xen,xen-";
        struct resource res;
+       unsigned long grant_frames;
 
        node = of_find_compatible_node(NULL, NULL, "xen,xen");
        if (!node) {
@@ -224,10 +251,14 @@ static int __init xen_guest_init(void)
        }
        if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res))
                return 0;
-       xen_hvm_resume_frames = res.start;
+       grant_frames = res.start;
        xen_events_irq = irq_of_parse_and_map(node, 0);
        pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n",
-                       version, xen_events_irq, (xen_hvm_resume_frames >> PAGE_SHIFT));
+                       version, xen_events_irq, (grant_frames >> PAGE_SHIFT));
+
+       if (xen_events_irq < 0)
+               return -ENODEV;
+
        xen_domain_type = XEN_HVM_DOMAIN;
 
        xen_setup_features();
@@ -265,6 +296,10 @@ static int __init xen_guest_init(void)
        if (xen_vcpu_info == NULL)
                return -ENOMEM;
 
+       if (gnttab_setup_auto_xlat_frames(grant_frames)) {
+               free_percpu(xen_vcpu_info);
+               return -ENOMEM;
+       }
        gnttab_init();
        if (!xen_initial_domain())
                xenbus_probe(NULL);
@@ -276,9 +311,21 @@ static int __init xen_guest_init(void)
        disable_cpuidle();
        disable_cpufreq();
 
+       xen_init_IRQ();
+
+       if (request_percpu_irq(xen_events_irq, xen_arm_callback,
+                              "events", &xen_vcpu)) {
+               pr_err("Error request IRQ %d\n", xen_events_irq);
+               return -EINVAL;
+       }
+
+       xen_percpu_init();
+
+       register_cpu_notifier(&xen_cpu_notifier);
+
        return 0;
 }
-core_initcall(xen_guest_init);
+early_initcall(xen_guest_init);
 
 static int __init xen_pm_init(void)
 {
@@ -292,31 +339,6 @@ static int __init xen_pm_init(void)
 }
 late_initcall(xen_pm_init);
 
-static irqreturn_t xen_arm_callback(int irq, void *arg)
-{
-       xen_hvm_evtchn_do_upcall();
-       return IRQ_HANDLED;
-}
-
-static int __init xen_init_events(void)
-{
-       if (!xen_domain() || xen_events_irq < 0)
-               return -ENODEV;
-
-       xen_init_IRQ();
-
-       if (request_percpu_irq(xen_events_irq, xen_arm_callback,
-                       "events", &xen_vcpu)) {
-               pr_err("Error requesting IRQ %d\n", xen_events_irq);
-               return -EINVAL;
-       }
-
-       on_each_cpu(xen_percpu_init, NULL, 0);
-
-       return 0;
-}
-postcore_initcall(xen_init_events);
-
 /* In the hypervisor.S file. */
 EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);