#include <linux/init.h>
 #include <linux/threads.h>
 
-struct device_node;
-
 /**
  * struct cpu_operations - Callback operations for hotplugging CPUs.
  *
  * @name:      Name of the property as appears in a devicetree cpu node's
- *             enable-method property.
- * @cpu_init:  Reads any data necessary for a specific enable-method from the
- *             devicetree, for a given cpu node and proposed logical id.
+ *             enable-method property. On systems booting with ACPI, @name
+ *             identifies the struct cpu_operations entry corresponding to
+ *             the boot protocol specified in the ACPI MADT table.
+ * @cpu_init:  Reads any data necessary for a specific enable-method for a
+ *             proposed logical id.
  * @cpu_prepare: Early one-time preparation step for a cpu. If there is a
  *             mechanism for doing so, tests whether it is possible to boot
  *             the given CPU.
  * @cpu_die:   Makes a cpu leave the kernel. Must not fail. Called from the
  *             cpu being killed.
  * @cpu_kill:  Ensures a cpu has left the kernel. Called from another cpu.
- * @cpu_init_idle: Reads any data necessary to initialize CPU idle states from
- *             devicetree, for a given cpu node and proposed logical id.
+ * @cpu_init_idle: Reads any data necessary to initialize CPU idle states for
+ *                a proposed logical id.
  * @cpu_suspend: Suspends a cpu and saves the required context. May fail owing
  *               to wrong parameters or error conditions. Called from the
  *               CPU being suspended. Must be called with IRQs disabled.
  */
 struct cpu_operations {
        const char      *name;
-       int             (*cpu_init)(struct device_node *, unsigned int);
+       int             (*cpu_init)(unsigned int);
        int             (*cpu_prepare)(unsigned int);
        int             (*cpu_boot)(unsigned int);
        void            (*cpu_postboot)(void);
        int             (*cpu_kill)(unsigned int cpu);
 #endif
 #ifdef CONFIG_CPU_IDLE
-       int             (*cpu_init_idle)(struct device_node *, unsigned int);
+       int             (*cpu_init_idle)(unsigned int);
        int             (*cpu_suspend)(unsigned long);
 #endif
 };
 
 extern const struct cpu_operations *cpu_ops[NR_CPUS];
-int __init cpu_read_ops(struct device_node *dn, int cpu);
-void __init cpu_read_bootcpu_ops(void);
+int __init cpu_read_ops(int cpu);
 const struct cpu_operations *cpu_get_ops(const char *name);
 
+static inline void __init cpu_read_bootcpu_ops(void)
+{
+       cpu_read_ops(0);
+}
+
 #endif /* ifndef __ASM_CPU_OPS_H */
 
                if (!cpu_ops[enabled_cpus])
                        return;
 
-               if (cpu_ops[enabled_cpus]->cpu_init(NULL, enabled_cpus))
+               if (cpu_ops[enabled_cpus]->cpu_init(enabled_cpus))
                        return;
 
                /* map the logical cpu id to cpu MPIDR */
 
 /*
  * Read a cpu's enable method from the device tree and record it in cpu_ops.
  */
-int __init cpu_read_ops(struct device_node *dn, int cpu)
+int __init cpu_read_ops(int cpu)
 {
-       const char *enable_method = of_get_property(dn, "enable-method", NULL);
+       const char *enable_method;
+       struct device_node *dn = of_get_cpu_node(cpu, NULL);
+
+       if (!dn) {
+               if (!cpu)
+                       pr_err("Failed to find device node for boot cpu\n");
+               return -ENODEV;
+       }
+
+       enable_method = of_get_property(dn, "enable-method", NULL);
        if (!enable_method) {
                /*
                 * The boot CPU may not have an enable method (e.g. when
 
        return 0;
 }
-
-void __init cpu_read_bootcpu_ops(void)
-{
-       struct device_node *dn = of_get_cpu_node(0, NULL);
-       if (!dn) {
-               pr_err("Failed to find device node for boot cpu\n");
-               return;
-       }
-       cpu_read_ops(dn, 0);
-}
 
 int arm_cpuidle_init(unsigned int cpu)
 {
        int ret = -EOPNOTSUPP;
-       struct device_node *cpu_node = of_cpu_device_node_get(cpu);
-
-       if (!cpu_node)
-               return -ENODEV;
 
        if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_init_idle)
-               ret = cpu_ops[cpu]->cpu_init_idle(cpu_node, cpu);
+               ret = cpu_ops[cpu]->cpu_init_idle(cpu);
 
-       of_node_put(cpu_node);
        return ret;
 }
 
 
        return err;
 }
 
-static int __maybe_unused cpu_psci_cpu_init_idle(struct device_node *cpu_node,
-                                                unsigned int cpu)
+static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu)
 {
        int i, ret, count = 0;
        struct psci_power_state *psci_states;
-       struct device_node *state_node;
+       struct device_node *state_node, *cpu_node;
+
+       cpu_node = of_get_cpu_node(cpu, NULL);
+       if (!cpu_node)
+               return -ENODEV;
 
        /*
         * If the PSCI cpu_suspend function hook has not been initialized
 
 #ifdef CONFIG_SMP
 
-static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu)
+static int __init cpu_psci_cpu_init(unsigned int cpu)
 {
        return 0;
 }
 
        set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
 }
 
+/*
+ * Initialize cpu operations for a logical cpu and
+ * set it in the possible mask on success
+ */
+static int __init smp_cpu_setup(int cpu)
+{
+       if (cpu_read_ops(cpu))
+               return -ENODEV;
+
+       if (cpu_ops[cpu]->cpu_init(cpu))
+               return -ENODEV;
+
+       set_cpu_possible(cpu, true);
+
+       return 0;
+}
+
 /*
  * Enumerate the possible CPU set from the device tree and build the
  * cpu logical map array containing MPIDR values related to logical
                if (cpu >= NR_CPUS)
                        goto next;
 
-               if (cpu_read_ops(dn, cpu) != 0)
-                       goto next;
-
-               if (cpu_ops[cpu]->cpu_init(dn, cpu))
-                       goto next;
-
                pr_debug("cpu logical map 0x%llx\n", hwid);
                cpu_logical_map(cpu) = hwid;
 next:
        }
 
        /*
-        * All the cpus that made it to the cpu_logical_map have been
-        * validated so set them as possible cpus.
+        * We need to set the cpu_logical_map entries before enabling
+        * the cpus so that cpu processor description entries (DT cpu nodes
+        * and ACPI MADT entries) can be retrieved by matching the cpu hwid
+        * with entries in cpu_logical_map while initializing the cpus.
+        * If the cpu set-up fails, invalidate the cpu_logical_map entry.
         */
-       for (i = 0; i < NR_CPUS; i++)
-               if (cpu_logical_map(i) != INVALID_HWID)
-                       set_cpu_possible(i, true);
+       for (i = 1; i < NR_CPUS; i++) {
+               if (cpu_logical_map(i) != INVALID_HWID) {
+                       if (smp_cpu_setup(i))
+                               cpu_logical_map(i) = INVALID_HWID;
+               }
+       }
 }
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
 
 }
 
 
-static int smp_spin_table_cpu_init(struct device_node *dn, unsigned int cpu)
+static int smp_spin_table_cpu_init(unsigned int cpu)
 {
+       struct device_node *dn;
+
+       dn = of_get_cpu_node(cpu, NULL);
+       if (!dn)
+               return -ENODEV;
+
        /*
         * Determine the address from which the CPU is polling.
         */