diff options
author | Murali Nalajala <mnalajal@codeaurora.org> | 2015-01-07 19:36:57 -0800 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:07:20 -0700 |
commit | 764f9334a3344049a5c52bb03f5d148c0deff9bc (patch) | |
tree | eb176d01ed7fdce598b1d33693d5aa8cbb100d3b /drivers | |
parent | 201050d5579263cb88d0e9e9de09ae8a98c45148 (diff) |
cpu_pm: Add level to the cluster pm notification
Cluster pm notifications without level information increases difficulty
and complexity for the registered drivers to figure out when the last
coherency level is going into power collapse.
Send notifications with level information that allows the registered
drivers to easily determine the cluster level that is going in/out of
power collapse.
There is an issue with this implementation. GIC driver saves and
restores the distributed registers as part of cluster notifications. On
newer platforms there are multiple cluster levels are defined (e.g l2,
cci etc). These cluster level notofications can happen independently.
On MSM platforms GIC is still active while the cluster sleeps in idle,
causing the GIC state to be overwritten with an incorrect previous state
of the interrupts. This leads to a system hang. Do not save and restore
on any L2 and higher cache coherency level sleep entry and exit.
Change-Id: I31918d6383f19e80fe3b064cfaf0b55e16b97eb6
Signed-off-by: Archana Sathyakumar <asathyak@codeaurora.org>
Signed-off-by: Murali Nalajala <mnalajal@codeaurora.org>
Signed-off-by: Mahesh Sivasubramanian <msivasub@codeaurora.org>
Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/irqchip/irq-gic.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 18252fd3bec6..087c31ab3326 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -766,7 +766,8 @@ static void gic_cpu_restore(unsigned int gic_nr) gic_cpu_if_up(&gic_data[gic_nr]); } -static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) +static int gic_notifier(struct notifier_block *self, unsigned long cmd, + void *aff_level) { int i; @@ -785,11 +786,20 @@ static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) gic_cpu_restore(i); break; case CPU_CLUSTER_PM_ENTER: - gic_dist_save(i); + /* + * Affinity level of the node + * eg: + * cpu level = 0 + * l2 level = 1 + * cci level = 2 + */ + if (!(unsigned long)aff_level) + gic_dist_save(i); break; case CPU_CLUSTER_PM_ENTER_FAILED: case CPU_CLUSTER_PM_EXIT: - gic_dist_restore(i); + if (!(unsigned long)aff_level) + gic_dist_restore(i); break; } } |