#include <linux/smp.h>
 #include <linux/of.h>
 #include <linux/reboot.h>
+#include <linux/slab.h>
 
 #include <asm/cputhreads.h>
 #include <asm/firmware.h>
 static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
 static bool rebooting, throttled;
 
+static struct chip {
+       unsigned int id;
+       bool throttled;
+} *chips;
+
+static int nr_chips;
+
 /*
  * Note: The set of pstates consists of contiguous integers, the
  * smallest of which is indicated by powernv_pstate_info.min, the
 static void powernv_cpufreq_throttle_check(unsigned int cpu)
 {
        unsigned long pmsr;
-       int pmsr_pmax, pmsr_lp;
+       int pmsr_pmax, pmsr_lp, i;
 
        pmsr = get_pmspr(SPRN_PMSR);
 
+       for (i = 0; i < nr_chips; i++)
+               if (chips[i].id == cpu_to_chip_id(cpu))
+                       break;
+
        /* Check for Pmax Capping */
        pmsr_pmax = (s8)PMSR_MAX(pmsr);
        if (pmsr_pmax != powernv_pstate_info.max) {
-               throttled = true;
-               pr_info("CPU %d Pmax is reduced to %d\n", cpu, pmsr_pmax);
-               pr_info("Max allowed Pstate is capped\n");
+               if (chips[i].throttled)
+                       goto next;
+               chips[i].throttled = true;
+               pr_info("CPU %d on Chip %u has Pmax reduced to %d\n", cpu,
+                       chips[i].id, pmsr_pmax);
+       } else if (chips[i].throttled) {
+               chips[i].throttled = false;
+               pr_info("CPU %d on Chip %u has Pmax restored to %d\n", cpu,
+                       chips[i].id, pmsr_pmax);
        }
 
        /*
         * Check for Psafe by reading LocalPstate
         * or check if Psafe_mode_active is set in PMSR.
         */
+next:
        pmsr_lp = (s8)PMSR_LP(pmsr);
        if ((pmsr_lp < powernv_pstate_info.min) ||
                                (pmsr & PMSR_PSAFE_ENABLE)) {
        .attr           = powernv_cpu_freq_attr,
 };
 
+static int init_chip_info(void)
+{
+       unsigned int chip[256];
+       unsigned int cpu, i;
+       unsigned int prev_chip_id = UINT_MAX;
+
+       for_each_possible_cpu(cpu) {
+               unsigned int id = cpu_to_chip_id(cpu);
+
+               if (prev_chip_id != id) {
+                       prev_chip_id = id;
+                       chip[nr_chips++] = id;
+               }
+       }
+
+       chips = kmalloc_array(nr_chips, sizeof(struct chip), GFP_KERNEL);
+       if (!chips)
+               return -ENOMEM;
+
+       for (i = 0; i < nr_chips; i++) {
+               chips[i].id = chip[i];
+               chips[i].throttled = false;
+       }
+
+       return 0;
+}
+
 static int __init powernv_cpufreq_init(void)
 {
        int rc = 0;
                return rc;
        }
 
+       /* Populate chip info */
+       rc = init_chip_info();
+       if (rc)
+               return rc;
+
        register_reboot_notifier(&powernv_cpufreq_reboot_nb);
        return cpufreq_register_driver(&powernv_cpufreq_driver);
 }