From: Colin Cross <hidden> Date: 2011-06-13 00:47:23
Remove __init annotation from l2x0_init so it can be used to
reinitialize the l2x0 after it has been reset during suspend.
Only print the init messages the first time l2x0_init is called.
Add l2x0_enable to re-enable the l2x0 after l2x0_disable if
the l2x0 was not reset.
l2x0_disable cannot use writel, as writel calls wmb(), and wmb()
may call outer_cache_sync, which takes the same spinlock as
l2x0_disable.
Signed-off-by: Colin Cross <redacted>
---
arch/arm/include/asm/hardware/cache-l2x0.h | 3 ++-
arch/arm/mm/cache-l2x0.c | 18 ++++++++++++++----
2 files changed, 16 insertions(+), 5 deletions(-)
@@ -261,16 +261,26 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)spin_unlock_irqrestore(&l2x0_lock,flags);}+/* enables l2x0 after l2x0_disable, does not invalidate */+voidl2x0_enable(void)+{+unsignedlongflags;++spin_lock_irqsave(&l2x0_lock,flags);+writel_relaxed(1,l2x0_base+L2X0_CTRL);+spin_unlock_irqrestore(&l2x0_lock,flags);+}+staticvoidl2x0_disable(void){unsignedlongflags;spin_lock_irqsave(&l2x0_lock,flags);-writel(0,l2x0_base+L2X0_CTRL);+writel_relaxed(0,l2x0_base+L2X0_CTRL);spin_unlock_irqrestore(&l2x0_lock,flags);}-void__initl2x0_init(void__iomem*base,__u32aux_val,__u32aux_mask)+voidl2x0_init(void__iomem*base,__u32aux_val,__u32aux_mask){__u32aux;__u32cache_id;
From: Lorenzo Pieralisi <hidden> Date: 2011-06-13 10:19:56
On Mon, Jun 13, 2011 at 01:46:58AM +0100, Colin Cross wrote:
Remove __init annotation from l2x0_init so it can be used to
reinitialize the l2x0 after it has been reset during suspend.
Only print the init messages the first time l2x0_init is called.
Add l2x0_enable to re-enable the l2x0 after l2x0_disable if
the l2x0 was not reset.
l2x0_disable cannot use writel, as writel calls wmb(), and wmb()
may call outer_cache_sync, which takes the same spinlock as
l2x0_disable.
Signed-off-by: Colin Cross <redacted>
---
arch/arm/include/asm/hardware/cache-l2x0.h | 3 ++-
arch/arm/mm/cache-l2x0.c | 18 ++++++++++++++----
2 files changed, 16 insertions(+), 5 deletions(-)
We might still need hooks to save/restore PL310 context since registers
like tag and data RAM control are gone on reset. Furthermore, on L2 RAM
retention we want to reinit L2 without having to invalidate L2 RAM(s),
which means we cannot use l2x0_init as it is. I added a couple of hooks to
outer_cache in order to carry out this task, patch coming.
Lorenzo
From: Colin Cross <hidden> Date: 2011-06-13 18:20:43
On Mon, Jun 13, 2011 at 3:19 AM, Lorenzo Pieralisi
[off-list ref] wrote:
On Mon, Jun 13, 2011 at 01:46:58AM +0100, Colin Cross wrote:
quoted
Remove __init annotation from l2x0_init so it can be used to
reinitialize the l2x0 after it has been reset during suspend.
Only print the init messages the first time l2x0_init is called.
Add l2x0_enable to re-enable the l2x0 after l2x0_disable if
the l2x0 was not reset.
l2x0_disable cannot use writel, as writel calls wmb(), and wmb()
may call outer_cache_sync, which takes the same spinlock as
l2x0_disable.
Signed-off-by: Colin Cross <redacted>
---
?arch/arm/include/asm/hardware/cache-l2x0.h | ? ?3 ++-
?arch/arm/mm/cache-l2x0.c ? ? ? ? ? ? ? ? ? | ? 18 ++++++++++++++----
?2 files changed, 16 insertions(+), 5 deletions(-)
This function is still dodgy to use, since we are disabling L2
possibly with current function stack lines allocated, which might wreak havoc.
From bogus@does.not.exist.com Wed Jun 1 12:03:18 2011
From: bogus@does.not.exist.com ()
Date: Wed, 01 Jun 2011 16:03:18 -0000
Subject: No subject
Message-ID: [off-list ref]
working with) flushes on disable. I had a problem where reads with
the cache disabled were getting incorrect data because the data was
stuck in the cache. With the CPU paused, I disabled the PL310 with
the L2X0_CTRL register, and my data appeared in memory. I'll try to
find some documentation to support this.
Otherwise, wouldn't a flush_cache_all() and l2x0_flush_all() in
l2x0_disable() ensure the stack lines were flushed out? Probably
needs a readl_releaxed as well, to ensure the disable has taken
effect.
We might still need hooks to save/restore PL310 context since registers
like tag and data RAM control are gone on reset. Furthermore, on L2 RAM
retention we want to reinit L2 without having to invalidate L2 RAM(s),
which means we cannot use l2x0_init as it is. I added a couple of hooks t=
o
outer_cache in order to carry out this task, patch coming.
I'm assuming that every platform has a function to set up the tag ram
control the way they want them, which then calls l2x0_init. That
platform cache init function can be called instead of directly calling
l2x0_init from the resume path.
Calling l2x0_enable instead of l2x0_init solves the retention problem.
From: Lorenzo Pieralisi <hidden> Date: 2011-06-14 17:30:34
On Mon, Jun 13, 2011 at 07:20:34PM +0100, Colin Cross wrote:
On Mon, Jun 13, 2011 at 3:19 AM, Lorenzo Pieralisi
[off-list ref] wrote:
quoted
On Mon, Jun 13, 2011 at 01:46:58AM +0100, Colin Cross wrote:
quoted
Remove __init annotation from l2x0_init so it can be used to
reinitialize the l2x0 after it has been reset during suspend.
Only print the init messages the first time l2x0_init is called.
Add l2x0_enable to re-enable the l2x0 after l2x0_disable if
the l2x0 was not reset.
l2x0_disable cannot use writel, as writel calls wmb(), and wmb()
may call outer_cache_sync, which takes the same spinlock as
l2x0_disable.
Signed-off-by: Colin Cross <redacted>
---
?arch/arm/include/asm/hardware/cache-l2x0.h | ? ?3 ++-
?arch/arm/mm/cache-l2x0.c ? ? ? ? ? ? ? ? ? | ? 18 ++++++++++++++----
?2 files changed, 16 insertions(+), 5 deletions(-)
This function is still dodgy to use, since we are disabling L2
possibly with current function stack lines allocated, which might wreak havoc.
From my JTAG debugging, I think the PL310 (at least the one I'm
working with) flushes on disable. I had a problem where reads with
the cache disabled were getting incorrect data because the data was
stuck in the cache. With the CPU paused, I disabled the PL310 with
the L2X0_CTRL register, and my data appeared in memory. I'll try to
find some documentation to support this.
According to the PL310 TRM (r3p2 3-9) on disable the PL310 syncs, which means
it flushes internal buffers, but it is not supposed to clean dirty lines.
It seems unsafe to me to use the stack and other cacheable data right before
disabling.
Otherwise, wouldn't a flush_cache_all() and l2x0_flush_all() in
l2x0_disable() ensure the stack lines were flushed out? Probably
needs a readl_releaxed as well, to ensure the disable has taken
effect.
I reckon the safest option is to clean and disable in one C
function. Moreover at that point in time spinlocks might not be an option
anymore (CPU out of coherency), which makes those functions unusable.
We might still need hooks to save/restore PL310 context since registers
like tag and data RAM control are gone on reset. Furthermore, on L2 RAM
retention we want to reinit L2 without having to invalidate L2 RAM(s),
which means we cannot use l2x0_init as it is. I added a couple of hooks to
outer_cache in order to carry out this task, patch coming.
I'm assuming that every platform has a function to set up the tag ram
control the way they want them, which then calls l2x0_init. That
platform cache init function can be called instead of directly calling
l2x0_init from the resume path.
I agree that it might solve the problem, and I understand that it allows
to reuse some code, but this will force us to call into platform code
to reinit L2 (which goes against the grain of platform notifiers);
if we manage to write a function doing the whole thing in
a single place it might be easier to use and factor out some replicated
code in the process.
Lorenzo
On Mon, Jun 13, 2011 at 07:20:34PM +0100, Colin Cross wrote:
quoted
On Mon, Jun 13, 2011 at 3:19 AM, Lorenzo Pieralisi
[off-list ref] wrote:
quoted
On Mon, Jun 13, 2011 at 01:46:58AM +0100, Colin Cross wrote:
quoted
Remove __init annotation from l2x0_init so it can be used to
reinitialize the l2x0 after it has been reset during suspend.
Only print the init messages the first time l2x0_init is called.
Add l2x0_enable to re-enable the l2x0 after l2x0_disable if
the l2x0 was not reset.
l2x0_disable cannot use writel, as writel calls wmb(), and wmb()
may call outer_cache_sync, which takes the same spinlock as
l2x0_disable.
Signed-off-by: Colin Cross<redacted>
---
?arch/arm/include/asm/hardware/cache-l2x0.h | ? ?3 ++-
?arch/arm/mm/cache-l2x0.c ? ? ? ? ? ? ? ? ? | ? 18 ++++++++++++++----
?2 files changed, 16 insertions(+), 5 deletions(-)
This function is still dodgy to use, since we are disabling L2
possibly with current function stack lines allocated, which might wreak havoc.
From my JTAG debugging, I think the PL310 (at least the one I'm
working with) flushes on disable. I had a problem where reads with
the cache disabled were getting incorrect data because the data was
stuck in the cache. With the CPU paused, I disabled the PL310 with
the L2X0_CTRL register, and my data appeared in memory. I'll try to
find some documentation to support this.
According to the PL310 TRM (r3p2 3-9) on disable the PL310 syncs, which means
it flushes internal buffers, but it is not supposed to clean dirty lines.
It seems unsafe to me to use the stack and other cacheable data right before
disabling.
That's right. Disabling L2 won't clean the cache lines. They need
to be cleaned before entering low power state where you loose
it.
Though, cleaning of L2 cache would work even with L2 enable
is not set.
From: Will Deacon <hidden> Date: 2011-06-15 09:03:30
Hi guys,
On Tue, Jun 14, 2011 at 06:30:19PM +0100, Lorenzo Pieralisi wrote:
On Mon, Jun 13, 2011 at 07:20:34PM +0100, Colin Cross wrote:
According to the PL310 TRM (r3p2 3-9) on disable the PL310 syncs, which means
it flushes internal buffers, but it is not supposed to clean dirty lines.
It seems unsafe to me to use the stack and other cacheable data right before
disabling.
quoted
Otherwise, wouldn't a flush_cache_all() and l2x0_flush_all() in
l2x0_disable() ensure the stack lines were flushed out? Probably
needs a readl_releaxed as well, to ensure the disable has taken
effect.
I reckon the safest option is to clean and disable in one C
function. Moreover at that point in time spinlocks might not be an option
anymore (CPU out of coherency), which makes those functions unusable.
I was planning to add this functionality as part of my kexec patches since
otherwise the l2x0_lock gets blown away on disable. I initially attributed
this to loss of coherency, but that's clearly not the case as I still had L1
running.
Colin - I'll add you to CC for v3 of that series.
Will
From: Barry Song <hidden> Date: 2011-07-28 07:43:51
2011/6/13 Colin Cross [off-list ref]:
Remove __init annotation from l2x0_init so it can be used to
reinitialize the l2x0 after it has been reset during suspend.
__init before l2x0_init can be deleted and make it available after resume.
We just tried the following flow for l2 cache on CSR SiRFprimaII, it
seems to be working:
suspend: sync and invalidate l2 cache, then disable L2
v7_flush_kern_cache_all
#ifdef CONFIG_CACHE_L2X0
ldr r0, =SIRFSOC_L2CC_VA_BASE
ldr r1, =L2X0_CLEAN_INV_WAY
mov r2, #0xff
str r2, [r0,r1]
mov r2, #0
1:
ldr r3, [r0,r1]
cmp r2,r3
bne 1b
ldr r1, =L2X0_CACHE_SYNC
mov r2, #0
str r2, [r0,r1]
ldr r1, =L2X0_CTRL
mov r2, #0
str r2, [r0,r1]
#endif
resume: re-initilized l2x:
l2x0_init((void __iomem *)SIRFSOC_L2CC_VA_BASE, 0x00040000, 0x00000000);
quoted hunk
Only print the init messages the first time l2x0_init is called.
Add l2x0_enable to re-enable the l2x0 after l2x0_disable if
the l2x0 was not reset.
l2x0_disable cannot use writel, as writel calls wmb(), and wmb()
may call outer_cache_sync, which takes the same spinlock as
l2x0_disable.
Signed-off-by: Colin Cross <redacted>
---
?arch/arm/include/asm/hardware/cache-l2x0.h | ? ?3 ++-
?arch/arm/mm/cache-l2x0.c ? ? ? ? ? ? ? ? ? | ? 18 ++++++++++++++----
?2 files changed, 16 insertions(+), 5 deletions(-)