* [PATCH 4/4] 8xx: Use SPRG2 and DAR registers to stash r11 and cr.
From: Joakim Tjernlund @ 2010-02-26 8:29 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1267172983-28721-4-git-send-email-Joakim.Tjernlund@transmode.se>
This avoids storing these registers in memory.
CPU6 errata will still use the old way.
Remove some G2 leftover accesses from 2.4
---
arch/powerpc/kernel/head_8xx.S | 49 +++++++++++++++++++++++++++++----------
1 files changed, 36 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 6478a96..1f1a04b 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -71,9 +71,6 @@ _ENTRY(_start);
* in the first level table, but that would require many changes to the
* Linux page directory/table functions that I don't want to do right now.
*
- * I used to use SPRG2 for a temporary register in the TLB handler, but it
- * has since been put to other uses. I now use a hack to save a register
- * and the CCR at memory location 0.....Someday I'll fix this.....
* -- Dan
*/
.globl __start
@@ -302,8 +299,13 @@ InstructionTLBMiss:
DO_8xx_CPU6(0x3f80, r3)
mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
mfcr r10
+#ifdef CONFIG_8xx_CPU6
stw r10, 0(r0)
stw r11, 4(r0)
+#else
+ mtspr SPRN_DAR, r10
+ mtspr SPRN_SPRG2, r11
+#endif
mfspr r10, SPRN_SRR0 /* Get effective address of fault */
#ifdef CONFIG_8xx_CPU15
addi r11, r10, 0x1000
@@ -359,13 +361,19 @@ InstructionTLBMiss:
DO_8xx_CPU6(0x2d80, r3)
mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
- mfspr r10, SPRN_M_TW /* Restore registers */
+ /* Restore registers */
+#ifndef CONFIG_8xx_CPU6
+ mfspr r10, SPRN_DAR
+ mtcr r10
+ mtspr SPRN_DAR, r11 /* Tag DAR */
+ mfspr r11, SPRN_SPRG2
+#else
lwz r11, 0(r0)
mtcr r11
lwz r11, 4(r0)
-#ifdef CONFIG_8xx_CPU6
lwz r3, 8(r0)
#endif
+ mfspr r10, SPRN_M_TW
rfi
2:
mfspr r11, SPRN_SRR1
@@ -375,13 +383,20 @@ InstructionTLBMiss:
rlwinm r11, r11, 0, 0xffff
mtspr SPRN_SRR1, r11
- mfspr r10, SPRN_M_TW /* Restore registers */
+ /* Restore registers */
+#ifndef CONFIG_8xx_CPU6
+ mfspr r10, SPRN_DAR
+ mtcr r10
+ li r11, 0x00f0
+ mtspr SPRN_DAR, r11 /* Tag DAR */
+ mfspr r11, SPRN_SPRG2
+#else
lwz r11, 0(r0)
mtcr r11
lwz r11, 4(r0)
-#ifdef CONFIG_8xx_CPU6
lwz r3, 8(r0)
#endif
+ mfspr r10, SPRN_M_TW
b InstructionAccess
. = 0x1200
@@ -392,8 +407,13 @@ DataStoreTLBMiss:
DO_8xx_CPU6(0x3f80, r3)
mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
mfcr r10
+#ifdef CONFIG_8xx_CPU6
stw r10, 0(r0)
stw r11, 4(r0)
+#else
+ mtspr SPRN_DAR, r10
+ mtspr SPRN_SPRG2, r11
+#endif
mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
/* If we are faulting a kernel address, we have to use the
@@ -461,18 +481,24 @@ DataStoreTLBMiss:
* of the MMU.
*/
2: li r11, 0x00f0
- mtspr SPRN_DAR,r11 /* Tag DAR */
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
DO_8xx_CPU6(0x3d80, r3)
mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
- mfspr r10, SPRN_M_TW /* Restore registers */
+ /* Restore registers */
+#ifndef CONFIG_8xx_CPU6
+ mfspr r10, SPRN_DAR
+ mtcr r10
+ mtspr SPRN_DAR, r11 /* Tag DAR */
+ mfspr r11, SPRN_SPRG2
+#else
+ mtspr SPRN_DAR, r11 /* Tag DAR */
lwz r11, 0(r0)
mtcr r11
lwz r11, 4(r0)
-#ifdef CONFIG_8xx_CPU6
lwz r3, 8(r0)
#endif
+ mfspr r10, SPRN_M_TW
rfi
/* This is an instruction TLB error on the MPC8xx. This could be due
@@ -684,9 +710,6 @@ start_here:
tophys(r4,r2)
addi r4,r4,THREAD /* init task's THREAD */
mtspr SPRN_SPRG_THREAD,r4
- li r3,0
- /* XXX What is that for ? SPRG2 appears otherwise unused on 8xx */
- mtspr SPRN_SPRG2,r3 /* 0 => r1 has kernel sp */
/* stack */
lis r1,init_thread_union@ha
--
1.6.4.4
^ permalink raw reply related
* [PATCH 3/4] 8xx: Don't touch ACCESSED when no SWAP.
From: Joakim Tjernlund @ 2010-02-26 8:29 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1267172983-28721-3-git-send-email-Joakim.Tjernlund@transmode.se>
Only the swap function cares about the ACCESSED bit in
the pte. Do not waste cycles updateting ACCESSED when swap
is not compiled into the kernel.
---
arch/powerpc/kernel/head_8xx.S | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 84ca1d9..6478a96 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -343,10 +343,11 @@ InstructionTLBMiss:
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
lwz r10, 0(r11) /* Get the pte */
+#ifdef CONFIG_SWAP
andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT
cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT
bne- cr0, 2f
-
+#endif
/* The Linux PTE won't go exactly into the MMU TLB.
* Software indicator bits 21 and 28 must be clear.
* Software indicator bits 24, 25, 26, and 27 must be
@@ -439,10 +440,11 @@ DataStoreTLBMiss:
* r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
* r10 = (r10 & ~PRESENT) | r11;
*/
+#ifdef CONFIG_SWAP
rlwinm r11, r10, 32-5, _PAGE_PRESENT
and r11, r11, r10
rlwimi r10, r11, 0, _PAGE_PRESENT
-
+#endif
/* Honour kernel RO, User NA */
/* 0x200 == Extended encoding, bit 22 */
rlwimi r10, r10, 32-2, 0x200 /* Copy USER to bit 22, 0x200 */
--
1.6.4.4
^ permalink raw reply related
* [PATCH 2/4] 8xx: Avoid testing for kernel space in ITLB Miss.
From: Joakim Tjernlund @ 2010-02-26 8:29 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1267172983-28721-2-git-send-email-Joakim.Tjernlund@transmode.se>
Only modules will cause ITLB Misses as we always pin
the first 8MB of kernel memory.
---
arch/powerpc/kernel/head_8xx.S | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index ecc4a02..84ca1d9 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -318,12 +318,16 @@ InstructionTLBMiss:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
+#ifdef CONFIG_MODULES
+ /* Only modules will cause ITLB Misses as we always
+ * pin the first 8MB of kernel memory */
andi. r11, r10, 0x0800 /* Address >= 0x80000000 */
beq 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
rlwimi r10, r11, 0, 2, 19
3:
+#endif
lwz r11, 0(r10) /* Get the level 1 entry */
rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
--
1.6.4.4
^ permalink raw reply related
* [PATCH 0/4] 8xx: Optimize TLB Miss code.
From: Joakim Tjernlund @ 2010-02-26 8:29 UTC (permalink / raw)
To: linuxppc-dev
This set of tries to optimize the TLB code on 8xx even
more. If they work, it should be a noticable performance
boost.
I would be very happy if you could test them for me.
Joakim Tjernlund (4):
8xx: Optimze TLB Miss handlers
8xx: Avoid testing for kernel space in ITLB Miss.
8xx: Don't touch ACCESSED when no SWAP.
8xx: Use SPRG2 and DAR registers to stash r11 and cr.
arch/powerpc/kernel/head_8xx.S | 70 +++++++++++++++++++++++++++-------------
1 files changed, 47 insertions(+), 23 deletions(-)
^ permalink raw reply
* [PATCH 1/4] 8xx: Optimze TLB Miss handlers
From: Joakim Tjernlund @ 2010-02-26 8:29 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1267172983-28721-1-git-send-email-Joakim.Tjernlund@transmode.se>
This removes a couple of insn's from the TLB Miss
handlers whithout changing functionality.
---
arch/powerpc/kernel/head_8xx.S | 11 +++--------
1 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 3ef743f..ecc4a02 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -343,17 +343,14 @@ InstructionTLBMiss:
cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT
bne- cr0, 2f
- /* Clear PP lsb, 0x400 */
- rlwinm r10, r10, 0, 22, 20
-
/* The Linux PTE won't go exactly into the MMU TLB.
- * Software indicator bits 22 and 28 must be clear.
+ * Software indicator bits 21 and 28 must be clear.
* Software indicator bits 24, 25, 26, and 27 must be
* set. All other Linux PTE bits control the behavior
* of the MMU.
*/
li r11, 0x00f0
- rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
+ rlwimi r10, r11, 0, 0x07f8 /* Set 24-27, clear 21-23,28 */
DO_8xx_CPU6(0x2d80, r3)
mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
@@ -444,9 +441,7 @@ DataStoreTLBMiss:
/* Honour kernel RO, User NA */
/* 0x200 == Extended encoding, bit 22 */
- /* r11 = (r10 & _PAGE_USER) >> 2 */
- rlwinm r11, r10, 32-2, 0x200
- or r10, r11, r10
+ rlwimi r10, r10, 32-2, 0x200 /* Copy USER to bit 22, 0x200 */
/* r11 = (r10 & _PAGE_RW) >> 1 */
rlwinm r11, r10, 32-1, 0x200
or r10, r11, r10
--
1.6.4.4
^ permalink raw reply related
* [PATCH] powerpc: Fix lwsync feature fixup vs. modules on 64-bit
From: Benjamin Herrenschmidt @ 2010-02-26 7:30 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Anton Blanchard
Anton's commit enabling the use of the lwsync fixup mechanism on 64-bit
breaks modules. The lwsync fixup section uses .long instead of the
FTR_ENTRY_OFFSET macro used by other fixups sections, and thus will
generate 32-bit relocations that our module loader cannot resolve.
This changes it to use the same type as other feature sections.
Note however that we might want to consider using 32-bit for all the
feature fixup offsets and add support for R_PPC_REL32 to module_64.c
instead as that would reduce the size of the kernel image. I'll leave
that as an exercise for the reader for now...
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/feature-fixups.h | 2 +-
arch/powerpc/lib/feature-fixups.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/feature-fixups.h b/arch/powerpc/include/asm/feature-fixups.h
index cbd4dfa..96a7d06 100644
--- a/arch/powerpc/include/asm/feature-fixups.h
+++ b/arch/powerpc/include/asm/feature-fixups.h
@@ -165,7 +165,7 @@ label##2: \
.pushsection sect,"a"; \
.align 2; \
label##3: \
- .long label##1b-label##3b; \
+ FTR_ENTRY_OFFSET label##1b-label##3b; \
.popsection;
#endif /* __ASM_POWERPC_FEATURE_FIXUPS_H */
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 4dee652..e640175 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -112,7 +112,8 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
{
- int *start, *end, *dest;
+ long *start, *end;
+ unsigned int *dest;
if (!(value & CPU_FTR_LWSYNC))
return ;
^ permalink raw reply related
* powerpc: bump SECTION_SIZE_BITS from 16MB to 256MB
From: Anton Blanchard @ 2010-02-26 6:18 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev
The current setting for SECTION_SIZE_BITS is quite small compared to
everyone else:
arch/powerpc/include/asm/sparsemem.h:#define SECTION_SIZE_BITS 24
arch/sparc/include/asm/sparsemem.h:#define SECTION_SIZE_BITS 30
arch/ia64/include/asm/sparsemem.h:#define SECTION_SIZE_BITS (30)
arch/s390/include/asm/sparsemem.h:#define SECTION_SIZE_BITS 28
arch/x86/include/asm/sparsemem.h:# define SECTION_SIZE_BITS 27
And it has proven to be an issue during boot on very large machines.
If hotplug memory is enabled, drivers/base/memory.c does this:
for (i = 0; i < NR_MEM_SECTIONS; i++) {
if (!present_section_nr(i))
continue;
err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE,
0, BOOT);
if (!ret)
ret = err;
}
Which creates a sysfs directory for every 16MB of memory. As a result
I'm seeing up to 30 minutes spent here during boot:
c000000000248ee0 .__sysfs_add_one+0x28/0x128
c0000000002492a8 .sysfs_add_one+0x38/0x188
c000000000249c88 .create_dir+0x70/0x138
c000000000249d98 .sysfs_create_dir+0x48/0x78
c00000000032bad8 .kobject_add_internal+0x140/0x308
c00000000032beb4 .kobject_init_and_add+0x4c/0x68
c00000000046c2c0 .sysdev_register+0xa0/0x220
c00000000047b1dc .add_memory_block+0x124/0x1e8
c0000000008d1f28 .memory_dev_init+0xf4/0x168
c0000000008d1b64 .driver_init+0x50/0x64
c000000000890378 .do_basic_setup+0x40/0xd4
I assume there are some O(n^2) issues in sysfs as we add all the memory
nodes. Bumping SECTION_SIZE_BITS to 256 MB drops the time to about 10
seconds and results in a much smaller /sys.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
--- linux-2.6.33/arch/powerpc/include/asm/sparsemem.h~ 2010-02-25 22:53:54.000000000 -0600
+++ linux-2.6.33/arch/powerpc/include/asm/sparsemem.h 2010-02-25 22:54:06.000000000 -0600
@@ -8,7 +8,7 @@
* MAX_PHYSADDR_BITS 2^N: how much physical address space we have
* MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space
*/
-#define SECTION_SIZE_BITS 24
+#define SECTION_SIZE_BITS 28
#define MAX_PHYSADDR_BITS 44
#define MAX_PHYSMEM_BITS 44
^ permalink raw reply
* [PATCH] powerpc: export data from new hcall H_EM_GET_PARMS
From: Vaidyanathan Srinivasan @ 2010-02-26 6:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Anton Blanchard; +Cc: linuxppc-dev
Hi,
A new hcall H_EM_GET_PARMS as been added to obtain power mode data
from the platform. This data can be used by user space administrative
tools for better power management.
The following patch add data from this new hcall into the lparcfg
driver and exports to user space along with other existing lpar data
in /proc/powerpc/lparcfg
Please review and include in powerpc tree.
Thanks,
Vaidy
---
powerpc: export data from new hcall H_EM_GET_PARMS
Add support for H_EM_GET_PARM hcall that will return data
related to power modes from the platform. Export the data
directly to user space for administrative tools to interpret
and use.
cat /proc/powerpc/lparcfg will export power mode data
Signed-off-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/hvcall.h | 1 +
arch/powerpc/kernel/lparcfg.c | 19 ++++++++++++++++++-
2 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index f027581..ebe7493 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -228,6 +228,7 @@
#define H_JOIN 0x298
#define H_VASI_STATE 0x2A4
#define H_ENABLE_CRQ 0x2B0
+#define H_GET_EM_PARMS 0x2B8
#define H_SET_MPP 0x2D0
#define H_GET_MPP 0x2D4
#define MAX_HCALL_OPCODE H_GET_MPP
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 79a00bb..2e7dd7e 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -37,7 +37,7 @@
#include <asm/vio.h>
#include <asm/mmu.h>
-#define MODULE_VERS "1.8"
+#define MODULE_VERS "1.9"
#define MODULE_NAME "lparcfg"
/* #define LPARCFG_DEBUG */
@@ -486,6 +486,21 @@ static void splpar_dispatch_data(struct seq_file *m)
seq_printf(m, "dispatch_dispersions=%lu\n", dispatch_dispersions);
}
+
+static void parse_em_data(struct seq_file *m)
+{
+ int rc;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ rc = plpar_hcall(H_GET_EM_PARMS, retbuf);
+
+ if (rc != H_SUCCESS)
+ return;
+
+ seq_printf(m, "power_mode_data=%016lx\n", retbuf[0]);
+ return;
+
+}
static int pseries_lparcfg_data(struct seq_file *m, void *v)
{
int partition_potential_processors;
@@ -540,6 +555,8 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
seq_printf(m, "slb_size=%d\n", mmu_slb_size);
+ parse_em_data(m);
+
return 0;
}
^ permalink raw reply related
* RE: Gianfar driver failing on MPC8641D based board
From: Kumar Gopalpet-B05799 @ 2010-02-26 4:58 UTC (permalink / raw)
To: avorontsov, Paul Gortmaker
Cc: netdev, linux-kernel, Martyn Welch, linuxppc-dev list, davem
In-Reply-To: <20100226031452.GA11319@oksana.dev.rtsoft.ru>
=20
>-----Original Message-----
>From: Anton Vorontsov [mailto:avorontsov@ru.mvista.com]=20
>Sent: Friday, February 26, 2010 8:45 AM
>To: Paul Gortmaker
>Cc: Martyn Welch; linuxppc-dev list; netdev@vger.kernel.org;=20
>linux-kernel@vger.kernel.org; Kumar Gopalpet-B05799;=20
>davem@davemloft.net; Kumar Gala
>Subject: Re: Gianfar driver failing on MPC8641D based board
>
>On Thu, Feb 25, 2010 at 07:53:30PM -0500, Paul Gortmaker wrote:
>[...]
>> I was able to reproduce it on an 8641D and bisected it down to this:
>>=20
>> -----------
>> commit a3bc1f11e9b867a4f49505ecac486a33af248b2e
>> Author: Anton Vorontsov <avorontsov@ru.mvista.com>
>> Date: Tue Nov 10 14:11:10 2009 +0000
>>=20
>> gianfar: Revive SKB recycling
>
>Thanks for the bisect. I have a guess why tx hangs in SMP=20
>case. Could anyone try the patch down below?
>
>[...]
>> ...which probably explains why you weren't seeing it on non-SMP.
>> I'd imagine it would show up on any of the e500mc boards too.
>
>Yeah.. Pity, I don't have SMP boards anymore. I'll try to get=20
>one though.
>
>
>diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c=20
>index 8bd3c9f..3ff3bd0 100644
>--- a/drivers/net/gianfar.c
>+++ b/drivers/net/gianfar.c
>@@ -2614,6 +2614,8 @@ static int gfar_poll(struct napi_struct=20
>*napi, int budget)
> tx_queue =3D priv->tx_queue[rx_queue->qindex];
>=20
> tx_cleaned +=3D gfar_clean_tx_ring(tx_queue);
>+ if (!tx_cleaned && !tx_queue->num_txbdfree)
>+ tx_cleaned +=3D 1; /* don't=20
>complete napi */
> rx_cleaned_per_queue =3D=20
>gfar_clean_rx_ring(rx_queue,
> =09
>budget_per_queue);
> rx_cleaned +=3D rx_cleaned_per_queue;
>
Anton,=20
There is also one more issue that I have been observing with the patch
"gianfar: Revive SKB recycling".
The issue is when I do a IPV4 forwarding test scenario with
bidirectional flows (SMP environment). I am using Spirent smart bits
(smartflow) for automation testing and I frequently observe smart flow
reporting "Rx packet counte greater than Tx packet count. Duplicate
packets might have been received".
To just get over the issue I have removed this patch and I didn't see
the issue.
To a certain extent I could get over the problem by using atomic_t for
num_txbdfree (atomic_add and atomic_dec instructions for updating the
num_txbdfree) and completely removing the spin_locks in the tx routines.
Also, I feel we might want to make some more changes to the
gfar_clean_tx_ring( ) and gfar_start_xmit() routines so that they can
operate parallely.=20
I am really sorry for not posting it a bit earlier as I am caught up
with some urgent issues.
--
Thanks
Sandeep
^ permalink raw reply
* Re: Gianfar driver failing on MPC8641D based board
From: Anton Vorontsov @ 2010-02-26 3:14 UTC (permalink / raw)
To: Paul Gortmaker
Cc: netdev, linux-kernel, Martyn Welch, linuxppc-dev list,
Sandeep Gopalpet, davem
In-Reply-To: <7d1d9c251002251653n6473f01ex2d43933ec6aa010b@mail.gmail.com>
On Thu, Feb 25, 2010 at 07:53:30PM -0500, Paul Gortmaker wrote:
[...]
> I was able to reproduce it on an 8641D and bisected it down to this:
>
> -----------
> commit a3bc1f11e9b867a4f49505ecac486a33af248b2e
> Author: Anton Vorontsov <avorontsov@ru.mvista.com>
> Date: Tue Nov 10 14:11:10 2009 +0000
>
> gianfar: Revive SKB recycling
Thanks for the bisect. I have a guess why tx hangs in
SMP case. Could anyone try the patch down below?
[...]
> ...which probably explains why you weren't seeing it on non-SMP.
> I'd imagine it would show up on any of the e500mc boards too.
Yeah.. Pity, I don't have SMP boards anymore. I'll try
to get one though.
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 8bd3c9f..3ff3bd0 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -2614,6 +2614,8 @@ static int gfar_poll(struct napi_struct *napi, int budget)
tx_queue = priv->tx_queue[rx_queue->qindex];
tx_cleaned += gfar_clean_tx_ring(tx_queue);
+ if (!tx_cleaned && !tx_queue->num_txbdfree)
+ tx_cleaned += 1; /* don't complete napi */
rx_cleaned_per_queue = gfar_clean_rx_ring(rx_queue,
budget_per_queue);
rx_cleaned += rx_cleaned_per_queue;
^ permalink raw reply related
* Does Linux 2.6.32 support NAND flash connect with MPC8247 through localbus with GPCM mode?
From: Peter Pan @ 2010-02-26 2:08 UTC (permalink / raw)
To: linuxppc-dev
I'm recently porting Linux 2.6.32 to our custom board with MPC8247. We have a
NAND flash connected using GPCM mode of local bus. But after I search
through the Linux
source, there is no compatible like "fsl,gpcm-nand". And I can not
find any driver
that seems works for our scene.
Does Linux 2.6.32 has the support for such nand device or I need to
construct my own
NAND driver using generic platform NAND driver?
^ permalink raw reply
* Re: [Patch 1/1] PPC64-HWBKPT: Implement hw-breakpoints for PPC64
From: Frederic Weisbecker @ 2010-02-26 1:58 UTC (permalink / raw)
To: K.Prasad
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Mahesh Salgaonkar, Will Deacon, David Gibson, linuxppc-dev,
Alan Stern, paulus, Roland McGrath
In-Reply-To: <20100222131746.GA3228@in.ibm.com>
On Mon, Feb 22, 2010 at 06:47:46PM +0530, K.Prasad wrote:
> The 'name' field here is actually a legacy inherited from x86 code. It
> is part of x86's arch-specific hw-breakpoint structure since:
> - inspired by the kprobe implementation which accepts symbol name as
> input.
> - kallsyms_lookup_name() was 'unexported' and a module could not resolve
> symbol names externally, so the core-infrastructure had to provide
> such facilities.
> - I wasn't sure about the discussions behind 'unexporting' of
> kallsyms_lookup_name(), so did not venture to export them again (which
> you rightfully did :-)
>
> Having said that, I'll be glad to remove this field (along with that in
> x86),
Cool, I'll integrate the x86 name field removal to the .24 series
> provided we know that there's a way for the user to resolve symbol
> names on its own i.e. routines like kallsyms_lookup_name() will remain
> exported.
Yeah, I guess it's fine to keep kallsyms_lookup_name() exported.
> > Also, do you think addr/len/type is enough to abstract out
> > any ppc breakpoints?
> >
> > This looks enough to me to express range breakpoints and
> > simple breakpoints. But what about value comparison?
> > (And still, there may be other trickier implementations
> > I don't know in ppc).
> >
>
> The above implementation is for PPC64 architecture that supports only
> 'simple' breakpoints of fixed length (no range breakpoints, no value
> comparison). More on that below.
Ok. I was just a bit confused in the middle of the several PPC breakpoint
implementations :)
> > > + /*
> > > + * As a policy, the callback is invoked in a 'trigger-after-execute'
> > > + * fashion
> > > + */
> > > + (bp->overflow_handler)(bp, 0, NULL, regs);
> >
> >
> > Why are you calling this explicitly instead of using the perf_bp_event()
> > thing? This looks like it won't work with perf as the event won't
> > be recorded by perf.
> >
>
> Yes, should have invoked perf_bp_event() for perf to work well (on a
> side note, it makes me wonder at the amount of 'extra' code that each
> breakpoint exception would execute if it were not called through perf
> sys-call...well, the costs of integrating with a generic infrastructure!)
It has the benefit of not adding extra checks in the breakpoint handler,
like checking the callback. Every breakpoint is treated the same way, which
makes the code more simple.
> > > +void ptrace_triggered(struct perf_event *bp, int nmi,
> > > + struct perf_sample_data *data, struct pt_regs *regs)
> > > +{
> > > + struct perf_event_attr attr;
> > > +
> > > + /*
> > > + * Disable the breakpoint request here since ptrace has defined a
> > > + * one-shot behaviour for breakpoint exceptions in PPC64.
> > > + * The SIGTRAP signal is generated automatically for us in do_dabr().
> > > + * We don't have to do anything about that here
> > > + */
> >
> >
> > Oh, why does ptrace use a one-shot behaviour in ppc? Breakpoints
> > only trigger once?
> >
>
> Yes, ptrace breakpoints on PPC64 are designed to trigger once and this
> patch retains that behaviour. It is very convenient to use one-shot
> behaviour on archs where exceptions are triggered-before-execute.
Ah, Why?
> > This looks fine for basic breakpoints. And this can probably be
> > improved to integrate ranges.
> >
> > But I think we did something wrong with the generic breakpoint
> > interface. We are translating the arch values to generic
> > attributes. Then this all will be translated back to arch
> > values.
> >
> > Having generic attributes is necessary for any perf event
> > use from userspace. But it looks like a waste for ptrace
> > that already gives us arch values. And the problem
> > is the same for x86.
> >
> > So I think we should implement a register_ptrace_breakpoint()
> > that doesn't take perf_event_attr but specific arch informations,
> > so that we don't need to pass through a generic conversion, which:
> >
>
> I agree that the layers of conversion from generic to arch-specific
> breakpoint constants is wasteful.
> Can't the arch_bp_generic_fields() function be moved to
> arch/x86/kernel/ptrace.c instead of a new interface?
I'll answer in your subsequent mail :)
> > - is wasteful
> > - won't be able to express 100% of any arch capabilities. We
> > can certainly express most arch breakpoints features through
> > the generic interface, but not all of them (given how tricky
> > the data value comparison features can be)
> >
> > I will rework that during the next cycle.
> >
> > Thanks.
> >
>
> Thank you for the comments. I will re-send a new version of the patch
> with the perf_bp_event() substitution.
Thanks.
^ permalink raw reply
* Re: Gianfar driver failing on MPC8641D based board
From: Paul Gortmaker @ 2010-02-26 0:53 UTC (permalink / raw)
To: avorontsov
Cc: netdev, linux-kernel, Martyn Welch, linuxppc-dev list,
Sandeep Gopalpet, davem
In-Reply-To: <20100225174935.GA32370@oksana.dev.rtsoft.ru>
On Thu, Feb 25, 2010 at 12:49 PM, Anton Vorontsov
<avorontsov@ru.mvista.com> wrote:
> On Thu, Feb 25, 2010 at 07:51:41PM +0300, Anton Vorontsov wrote:
>> On Thu, Feb 25, 2010 at 04:46:54PM +0000, Martyn Welch wrote:
>> [...]
>> > > nfs: server 192.168.0.1 not responding, still trying
>> > >
>> >
>> > Further testing has shown that this isn't restricted to warm reboots, it
>> > happens from cold as well. In addition, the exact timing of the failure
>> > seems to vary, some boots have got further before failing.
>>
>> Unfortunately I don't have any 8641 boards near me, so I can't
>> debug this myself. Though, I tested gianfar on MPC8568E-MDS with
>> 2.6.33 kernel, and it seems to work just fine.
>>
>> I see you use SMP. Can you try to turn it off? If that will fix
>> the issue, then it'll be a good data point.
>>
>> Meanwhile, I'll try SMP kernel on MPC8568 (UP), and let you
>> know the results.
>
> Nope, no luck. Can't trigger the issue. :-/
> Tested with NFS boot, TCP and UDP netperf tests.
I was able to reproduce it on an 8641D and bisected it down to this:
-----------
commit a3bc1f11e9b867a4f49505ecac486a33af248b2e
Author: Anton Vorontsov <avorontsov@ru.mvista.com>
Date: Tue Nov 10 14:11:10 2009 +0000
gianfar: Revive SKB recycling
Before calling gfar_clean_tx_ring() the driver grabs an irqsave
spinlock, and then tries to recycle skbs. But since
skb_recycle_check() returns 0 with IRQs disabled, we'll never
recycle any skbs.
It appears that gfar_clean_tx_ring() and gfar_start_xmit() are
mostly idependent and can work in parallel, except when they
modify num_txbdfree.
So we can drop the lock from most sections and thus fix the skb
recycling.
-----------
...which probably explains why you weren't seeing it on non-SMP.
I'd imagine it would show up on any of the e500mc boards too.
I'd done a rev-list on gianfar.[ch] from 32 to 33-rc1, and then
cherry-picked those onto a 32 baseline to reduce the scale of
the bisection, but I don't think that should impact the final
result I got in any meaningful way.
Paul.
^ permalink raw reply
* [PATCH 2/2] perf_event: e500 support
From: Scott Wood @ 2010-02-26 0:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
This implements perf_event support for the Freescale embedded performance
monitor, based on the existing perf_event.c that supports server/classic
chips.
Some limitations:
- Performance monitor interrupts are regular EE interrupts, and thus you
can't profile places with interrupts disabled. We may want to implement
soft IRQ-disabling, with perfmon interrupts exempted and treated as NMIs.
- When trying to schedule multiple event groups at once, and using
restricted events, situations could arise where scheduling fails even
though it would be possible. Consider three groups, each with two events.
One group has restricted events, the others don't. The two non-restricted
groups are scheduled, then one is removed, which happens to occupy the two
counters that can't do restricted events. The remaining non-restricted
group will not be moved to the non-restricted-capable counters to make
room if the restricted group tries to be scheduled.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
Changes from previous version:
- Factored out callchain makefile patch
- Split up header files
- Renamed pmu struct
- Added threshold support
arch/powerpc/include/asm/perf_event.h | 133 +----
arch/powerpc/include/asm/perf_event_fsl_emb.h | 50 ++
.../asm/{perf_event.h => perf_event_server.h} | 4 +-
arch/powerpc/include/asm/reg_fsl_emb.h | 2 +-
arch/powerpc/kernel/Makefile | 4 +
arch/powerpc/kernel/cputable.c | 2 +-
arch/powerpc/kernel/e500-pmu.c | 129 ++++
arch/powerpc/kernel/perf_event_fsl_emb.c | 654 ++++++++++++++++++++
arch/powerpc/platforms/Kconfig.cputype | 10 +
9 files changed, 874 insertions(+), 114 deletions(-)
rewrite arch/powerpc/include/asm/perf_event.h (92%)
create mode 100644 arch/powerpc/include/asm/perf_event_fsl_emb.h
rename arch/powerpc/include/asm/{perf_event.h => perf_event_server.h} (98%)
create mode 100644 arch/powerpc/kernel/e500-pmu.c
create mode 100644 arch/powerpc/kernel/perf_event_fsl_emb.c
diff --git a/arch/powerpc/include/asm/perf_event.h b/arch/powerpc/include/asm/perf_event.h
dissimilarity index 92%
index 3288ce3..e6d4ce6 100644
--- a/arch/powerpc/include/asm/perf_event.h
+++ b/arch/powerpc/include/asm/perf_event.h
@@ -1,110 +1,23 @@
-/*
- * Performance event support - PowerPC-specific definitions.
- *
- * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <linux/types.h>
-
-#include <asm/hw_irq.h>
-
-#define MAX_HWEVENTS 8
-#define MAX_EVENT_ALTERNATIVES 8
-#define MAX_LIMITED_HWCOUNTERS 2
-
-/*
- * This struct provides the constants and functions needed to
- * describe the PMU on a particular POWER-family CPU.
- */
-struct power_pmu {
- const char *name;
- int n_counter;
- int max_alternatives;
- unsigned long add_fields;
- unsigned long test_adder;
- int (*compute_mmcr)(u64 events[], int n_ev,
- unsigned int hwc[], unsigned long mmcr[]);
- int (*get_constraint)(u64 event_id, unsigned long *mskp,
- unsigned long *valp);
- int (*get_alternatives)(u64 event_id, unsigned int flags,
- u64 alt[]);
- void (*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
- int (*limited_pmc_event)(u64 event_id);
- u32 flags;
- int n_generic;
- int *generic_events;
- int (*cache_events)[PERF_COUNT_HW_CACHE_MAX]
- [PERF_COUNT_HW_CACHE_OP_MAX]
- [PERF_COUNT_HW_CACHE_RESULT_MAX];
-};
-
-/*
- * Values for power_pmu.flags
- */
-#define PPMU_LIMITED_PMC5_6 1 /* PMC5/6 have limited function */
-#define PPMU_ALT_SIPR 2 /* uses alternate posn for SIPR/HV */
-
-/*
- * Values for flags to get_alternatives()
- */
-#define PPMU_LIMITED_PMC_OK 1 /* can put this on a limited PMC */
-#define PPMU_LIMITED_PMC_REQD 2 /* have to put this on a limited PMC */
-#define PPMU_ONLY_COUNT_RUN 4 /* only counting in run state */
-
-extern int register_power_pmu(struct power_pmu *);
-
-struct pt_regs;
-extern unsigned long perf_misc_flags(struct pt_regs *regs);
-extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
-
-#define PERF_EVENT_INDEX_OFFSET 1
-
-/*
- * Only override the default definitions in include/linux/perf_event.h
- * if we have hardware PMU support.
- */
-#ifdef CONFIG_PPC_PERF_CTRS
-#define perf_misc_flags(regs) perf_misc_flags(regs)
-#endif
-
-/*
- * The power_pmu.get_constraint function returns a 32/64-bit value and
- * a 32/64-bit mask that express the constraints between this event_id and
- * other events.
- *
- * The value and mask are divided up into (non-overlapping) bitfields
- * of three different types:
- *
- * Select field: this expresses the constraint that some set of bits
- * in MMCR* needs to be set to a specific value for this event_id. For a
- * select field, the mask contains 1s in every bit of the field, and
- * the value contains a unique value for each possible setting of the
- * MMCR* bits. The constraint checking code will ensure that two events
- * that set the same field in their masks have the same value in their
- * value dwords.
- *
- * Add field: this expresses the constraint that there can be at most
- * N events in a particular class. A field of k bits can be used for
- * N <= 2^(k-1) - 1. The mask has the most significant bit of the field
- * set (and the other bits 0), and the value has only the least significant
- * bit of the field set. In addition, the 'add_fields' and 'test_adder'
- * in the struct power_pmu for this processor come into play. The
- * add_fields value contains 1 in the LSB of the field, and the
- * test_adder contains 2^(k-1) - 1 - N in the field.
- *
- * NAND field: this expresses the constraint that you may not have events
- * in all of a set of classes. (For example, on PPC970, you can't select
- * events from the FPU, ISU and IDU simultaneously, although any two are
- * possible.) For N classes, the field is N+1 bits wide, and each class
- * is assigned one bit from the least-significant N bits. The mask has
- * only the most-significant bit set, and the value has only the bit
- * for the event_id's class set. The test_adder has the least significant
- * bit set in the field.
- *
- * If an event_id is not subject to the constraint expressed by a particular
- * field, then it will have 0 in both the mask and value for that field.
- */
+/*
+ * Performance event support - hardware-specific disambiguation
+ *
+ * For now this is a compile-time decision, but eventually it should be
+ * runtime. This would allow multiplatform perf event support for e300 (fsl
+ * embedded perf counters) plus server/classic, and would accommodate
+ * devices other than the core which provide their own performance counters.
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifdef CONFIG_PPC_PERF_CTRS
+#include <asm/perf_event_server.h>
+#endif
+
+#ifdef CONFIG_FSL_EMB_PERF_EVENT
+#include <asm/perf_event_fsl_emb.h>
+#endif
diff --git a/arch/powerpc/include/asm/perf_event_fsl_emb.h b/arch/powerpc/include/asm/perf_event_fsl_emb.h
new file mode 100644
index 0000000..718a9fa
--- /dev/null
+++ b/arch/powerpc/include/asm/perf_event_fsl_emb.h
@@ -0,0 +1,50 @@
+/*
+ * Performance event support - Freescale embedded specific definitions.
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/hw_irq.h>
+
+#define MAX_HWEVENTS 4
+
+/* event flags */
+#define FSL_EMB_EVENT_VALID 1
+#define FSL_EMB_EVENT_RESTRICTED 2
+
+/* upper half of event flags is PMLCb */
+#define FSL_EMB_EVENT_THRESHMUL 0x0000070000000000ULL
+#define FSL_EMB_EVENT_THRESH 0x0000003f00000000ULL
+
+struct fsl_emb_pmu {
+ const char *name;
+ int n_counter; /* total number of counters */
+
+ /*
+ * The number of contiguous counters starting at zero that
+ * can hold restricted events, or zero if there are no
+ * restricted events.
+ *
+ * This isn't a very flexible method of expressing constraints,
+ * but it's very simple and is adequate for existing chips.
+ */
+ int n_restricted;
+
+ /* Returns event flags and PMLCb (FSL_EMB_EVENT_*) */
+ u64 (*xlate_event)(u64 event_id);
+
+ int n_generic;
+ int *generic_events;
+ int (*cache_events)[PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX];
+};
+
+int register_fsl_emb_pmu(struct fsl_emb_pmu *);
diff --git a/arch/powerpc/include/asm/perf_event.h b/arch/powerpc/include/asm/perf_event_server.h
similarity index 98%
rename from arch/powerpc/include/asm/perf_event.h
rename to arch/powerpc/include/asm/perf_event_server.h
index 3288ce3..8f1df12 100644
--- a/arch/powerpc/include/asm/perf_event.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -1,5 +1,5 @@
/*
- * Performance event support - PowerPC-specific definitions.
+ * Performance event support - PowerPC classic/server specific definitions.
*
* Copyright 2008-2009 Paul Mackerras, IBM Corporation.
*
@@ -8,8 +8,8 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/types.h>
+#include <linux/types.h>
#include <asm/hw_irq.h>
#define MAX_HWEVENTS 8
diff --git a/arch/powerpc/include/asm/reg_fsl_emb.h b/arch/powerpc/include/asm/reg_fsl_emb.h
index 0de404d..77bb71c 100644
--- a/arch/powerpc/include/asm/reg_fsl_emb.h
+++ b/arch/powerpc/include/asm/reg_fsl_emb.h
@@ -31,7 +31,7 @@
#define PMLCA_FCM0 0x08000000 /* Freeze when PMM==0 */
#define PMLCA_CE 0x04000000 /* Condition Enable */
-#define PMLCA_EVENT_MASK 0x007f0000 /* Event field */
+#define PMLCA_EVENT_MASK 0x00ff0000 /* Event field */
#define PMLCA_EVENT_SHIFT 16
#define PMRN_PMLCB0 0x110 /* PM Local Control B0 */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 93fd162..8773263 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -99,11 +99,15 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
+
obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o
obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \
power5+-pmu.o power6-pmu.o power7-pmu.o
obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o
+obj-$(CONFIG_FSL_EMB_PERF_EVENT) += perf_event_fsl_emb.o
+obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o
+
obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
ifneq ($(CONFIG_PPC_INDIRECT_IO),y)
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 2fc82ba..8af4949 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1808,7 +1808,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.icache_bsize = 64,
.dcache_bsize = 64,
.num_pmcs = 4,
- .oprofile_cpu_type = "ppc/e500", /* xxx - galak, e500mc? */
+ .oprofile_cpu_type = "ppc/e500mc",
.oprofile_type = PPC_OPROFILE_FSL_EMB,
.cpu_setup = __setup_cpu_e500mc,
.machine_check = machine_check_e500,
diff --git a/arch/powerpc/kernel/e500-pmu.c b/arch/powerpc/kernel/e500-pmu.c
new file mode 100644
index 0000000..7c07de0
--- /dev/null
+++ b/arch/powerpc/kernel/e500-pmu.c
@@ -0,0 +1,129 @@
+/*
+ * Performance counter support for e500 family processors.
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/string.h>
+#include <linux/perf_event.h>
+#include <asm/reg.h>
+#include <asm/cputable.h>
+
+/*
+ * Map of generic hardware event types to hardware events
+ * Zero if unsupported
+ */
+static int e500_generic_events[] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = 1,
+ [PERF_COUNT_HW_INSTRUCTIONS] = 2,
+ [PERF_COUNT_HW_CACHE_MISSES] = 41, /* Data L1 cache reloads */
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 12,
+ [PERF_COUNT_HW_BRANCH_MISSES] = 15,
+};
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ */
+static int e500_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+ /*
+ * D-cache misses are not split into read/write/prefetch;
+ * use raw event 41.
+ */
+ [C(L1D)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 27, 0 },
+ [C(OP_WRITE)] = { 28, 0 },
+ [C(OP_PREFETCH)] = { 29, 0 },
+ },
+ [C(L1I)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 2, 60 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { 0, 0 },
+ },
+ /*
+ * Assuming LL means L2, it's not a good match for this model.
+ * It allocates only on L1 castout or explicit prefetch, and
+ * does not have separate read/write events (but it does have
+ * separate instruction/data events).
+ */
+ [C(LL)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 0, 0 },
+ [C(OP_WRITE)] = { 0, 0 },
+ [C(OP_PREFETCH)] = { 0, 0 },
+ },
+ /*
+ * There are data/instruction MMU misses, but that's a miss on
+ * the chip's internal level-one TLB which is probably not
+ * what the user wants. Instead, unified level-two TLB misses
+ * are reported here.
+ */
+ [C(DTLB)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 26, 66 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
+ [C(BPU)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 12, 15 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
+};
+
+static int num_events = 128;
+
+/* Upper half of event id is PMLCb, for threshold events */
+static u64 e500_xlate_event(u64 event_id)
+{
+ u32 event_low = (u32)event_id;
+ u64 ret;
+
+ if (event_low >= num_events)
+ return 0;
+
+ ret = FSL_EMB_EVENT_VALID;
+
+ if (event_low >= 76 && event_low <= 81) {
+ ret |= FSL_EMB_EVENT_RESTRICTED;
+ ret |= event_id &
+ (FSL_EMB_EVENT_THRESHMUL | FSL_EMB_EVENT_THRESH);
+ } else if (event_id &
+ (FSL_EMB_EVENT_THRESHMUL | FSL_EMB_EVENT_THRESH)) {
+ /* Threshold requested on non-threshold event */
+ return 0;
+ }
+
+ return ret;
+}
+
+static struct fsl_emb_pmu e500_pmu = {
+ .name = "e500 family",
+ .n_counter = 4,
+ .n_restricted = 2,
+ .xlate_event = e500_xlate_event,
+ .n_generic = ARRAY_SIZE(e500_generic_events),
+ .generic_events = e500_generic_events,
+ .cache_events = &e500_cache_events,
+};
+
+static int init_e500_pmu(void)
+{
+ if (!cur_cpu_spec->oprofile_cpu_type)
+ return -ENODEV;
+
+ if (!strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/e500mc"))
+ num_events = 256;
+ else if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/e500"))
+ return -ENODEV;
+
+ return register_fsl_emb_pmu(&e500_pmu);
+}
+
+arch_initcall(init_e500_pmu);
diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c
new file mode 100644
index 0000000..369872f
--- /dev/null
+++ b/arch/powerpc/kernel/perf_event_fsl_emb.c
@@ -0,0 +1,654 @@
+/*
+ * Performance event support - Freescale Embedded Performance Monitor
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/perf_event.h>
+#include <linux/percpu.h>
+#include <linux/hardirq.h>
+#include <asm/reg_fsl_emb.h>
+#include <asm/pmc.h>
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+#include <asm/ptrace.h>
+
+struct cpu_hw_events {
+ int n_events;
+ int disabled;
+ u8 pmcs_enabled;
+ struct perf_event *event[MAX_HWEVENTS];
+};
+static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+
+static struct fsl_emb_pmu *ppmu;
+
+/* Number of perf_events counting hardware events */
+static atomic_t num_events;
+/* Used to avoid races in calling reserve/release_pmc_hardware */
+static DEFINE_MUTEX(pmc_reserve_mutex);
+
+/*
+ * If interrupts were soft-disabled when a PMU interrupt occurs, treat
+ * it as an NMI.
+ */
+static inline int perf_intr_is_nmi(struct pt_regs *regs)
+{
+#ifdef __powerpc64__
+ return !regs->softe;
+#else
+ return 0;
+#endif
+}
+
+static void perf_event_interrupt(struct pt_regs *regs);
+
+/*
+ * Read one performance monitor counter (PMC).
+ */
+static unsigned long read_pmc(int idx)
+{
+ unsigned long val;
+
+ switch (idx) {
+ case 0:
+ val = mfpmr(PMRN_PMC0);
+ break;
+ case 1:
+ val = mfpmr(PMRN_PMC1);
+ break;
+ case 2:
+ val = mfpmr(PMRN_PMC2);
+ break;
+ case 3:
+ val = mfpmr(PMRN_PMC3);
+ break;
+ default:
+ printk(KERN_ERR "oops trying to read PMC%d\n", idx);
+ val = 0;
+ }
+ return val;
+}
+
+/*
+ * Write one PMC.
+ */
+static void write_pmc(int idx, unsigned long val)
+{
+ switch (idx) {
+ case 0:
+ mtpmr(PMRN_PMC0, val);
+ break;
+ case 1:
+ mtpmr(PMRN_PMC1, val);
+ break;
+ case 2:
+ mtpmr(PMRN_PMC2, val);
+ break;
+ case 3:
+ mtpmr(PMRN_PMC3, val);
+ break;
+ default:
+ printk(KERN_ERR "oops trying to write PMC%d\n", idx);
+ }
+
+ isync();
+}
+
+/*
+ * Write one local control A register
+ */
+static void write_pmlca(int idx, unsigned long val)
+{
+ switch (idx) {
+ case 0:
+ mtpmr(PMRN_PMLCA0, val);
+ break;
+ case 1:
+ mtpmr(PMRN_PMLCA1, val);
+ break;
+ case 2:
+ mtpmr(PMRN_PMLCA2, val);
+ break;
+ case 3:
+ mtpmr(PMRN_PMLCA3, val);
+ break;
+ default:
+ printk(KERN_ERR "oops trying to write PMLCA%d\n", idx);
+ }
+
+ isync();
+}
+
+/*
+ * Write one local control B register
+ */
+static void write_pmlcb(int idx, unsigned long val)
+{
+ switch (idx) {
+ case 0:
+ mtpmr(PMRN_PMLCB0, val);
+ break;
+ case 1:
+ mtpmr(PMRN_PMLCB1, val);
+ break;
+ case 2:
+ mtpmr(PMRN_PMLCB2, val);
+ break;
+ case 3:
+ mtpmr(PMRN_PMLCB3, val);
+ break;
+ default:
+ printk(KERN_ERR "oops trying to write PMLCB%d\n", idx);
+ }
+
+ isync();
+}
+
+static void fsl_emb_pmu_read(struct perf_event *event)
+{
+ s64 val, delta, prev;
+
+ /*
+ * Performance monitor interrupts come even when interrupts
+ * are soft-disabled, as long as interrupts are hard-enabled.
+ * Therefore we treat them like NMIs.
+ */
+ do {
+ prev = atomic64_read(&event->hw.prev_count);
+ barrier();
+ val = read_pmc(event->hw.idx);
+ } while (atomic64_cmpxchg(&event->hw.prev_count, prev, val) != prev);
+
+ /* The counters are only 32 bits wide */
+ delta = (val - prev) & 0xfffffffful;
+ atomic64_add(delta, &event->count);
+ atomic64_sub(delta, &event->hw.period_left);
+}
+
+/*
+ * Disable all events to prevent PMU interrupts and to allow
+ * events to be added or removed.
+ */
+void hw_perf_disable(void)
+{
+ struct cpu_hw_events *cpuhw;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ cpuhw = &__get_cpu_var(cpu_hw_events);
+
+ if (!cpuhw->disabled) {
+ cpuhw->disabled = 1;
+
+ /*
+ * Check if we ever enabled the PMU on this cpu.
+ */
+ if (!cpuhw->pmcs_enabled) {
+ ppc_enable_pmcs();
+ cpuhw->pmcs_enabled = 1;
+ }
+
+ if (atomic_read(&num_events)) {
+ /*
+ * Set the 'freeze all counters' bit, and disable
+ * interrupts. The barrier is to make sure the
+ * mtpmr has been executed and the PMU has frozen
+ * the events before we return.
+ */
+
+ mtpmr(PMRN_PMGC0, PMGC0_FAC);
+ isync();
+ }
+ }
+ local_irq_restore(flags);
+}
+
+/*
+ * Re-enable all events if disable == 0.
+ * If we were previously disabled and events were added, then
+ * put the new config on the PMU.
+ */
+void hw_perf_enable(void)
+{
+ struct cpu_hw_events *cpuhw;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ cpuhw = &__get_cpu_var(cpu_hw_events);
+ if (!cpuhw->disabled)
+ goto out;
+
+ cpuhw->disabled = 0;
+ ppc_set_pmu_inuse(cpuhw->n_events != 0);
+
+ if (cpuhw->n_events > 0) {
+ mtpmr(PMRN_PMGC0, PMGC0_PMIE | PMGC0_FCECE);
+ isync();
+ }
+
+ out:
+ local_irq_restore(flags);
+}
+
+static int collect_events(struct perf_event *group, int max_count,
+ struct perf_event *ctrs[])
+{
+ int n = 0;
+ struct perf_event *event;
+
+ if (!is_software_event(group)) {
+ if (n >= max_count)
+ return -1;
+ ctrs[n] = group;
+ n++;
+ }
+ list_for_each_entry(event, &group->sibling_list, group_entry) {
+ if (!is_software_event(event) &&
+ event->state != PERF_EVENT_STATE_OFF) {
+ if (n >= max_count)
+ return -1;
+ ctrs[n] = event;
+ n++;
+ }
+ }
+ return n;
+}
+
+/* perf must be disabled, context locked on entry */
+static int fsl_emb_pmu_enable(struct perf_event *event)
+{
+ struct cpu_hw_events *cpuhw;
+ int ret = -EAGAIN;
+ int num_counters = ppmu->n_counter;
+ u64 val;
+ int i;
+
+ cpuhw = &get_cpu_var(cpu_hw_events);
+
+ if (event->hw.config & FSL_EMB_EVENT_RESTRICTED)
+ num_counters = ppmu->n_restricted;
+
+ /*
+ * Allocate counters from top-down, so that restricted-capable
+ * counters are kept free as long as possible.
+ */
+ for (i = num_counters - 1; i >= 0; i--) {
+ if (cpuhw->event[i])
+ continue;
+
+ break;
+ }
+
+ if (i < 0)
+ goto out;
+
+ event->hw.idx = i;
+ cpuhw->event[i] = event;
+ ++cpuhw->n_events;
+
+ val = 0;
+ if (event->hw.sample_period) {
+ s64 left = atomic64_read(&event->hw.period_left);
+ if (left < 0x80000000L)
+ val = 0x80000000L - left;
+ }
+ atomic64_set(&event->hw.prev_count, val);
+ write_pmc(i, val);
+ perf_event_update_userpage(event);
+
+ write_pmlcb(i, event->hw.config >> 32);
+ write_pmlca(i, event->hw.config_base);
+
+ ret = 0;
+ out:
+ put_cpu_var(cpu_hw_events);
+ return ret;
+}
+
+/* perf must be disabled, context locked on entry */
+static void fsl_emb_pmu_disable(struct perf_event *event)
+{
+ struct cpu_hw_events *cpuhw;
+ int i = event->hw.idx;
+
+ if (i < 0)
+ goto out;
+
+ fsl_emb_pmu_read(event);
+
+ cpuhw = &get_cpu_var(cpu_hw_events);
+
+ WARN_ON(event != cpuhw->event[event->hw.idx]);
+
+ write_pmlca(i, 0);
+ write_pmlcb(i, 0);
+ write_pmc(i, 0);
+
+ cpuhw->event[i] = NULL;
+ event->hw.idx = -1;
+
+ /*
+ * TODO: if at least one restricted event exists, and we
+ * just freed up a non-restricted-capable counter, and
+ * there is a restricted-capable counter occupied by
+ * a non-restricted event, migrate that event to the
+ * vacated counter.
+ */
+
+ cpuhw->n_events--;
+
+ out:
+ put_cpu_var(cpu_hw_events);
+}
+
+/*
+ * Re-enable interrupts on a event after they were throttled
+ * because they were coming too fast.
+ *
+ * Context is locked on entry, but perf is not disabled.
+ */
+static void fsl_emb_pmu_unthrottle(struct perf_event *event)
+{
+ s64 val, left;
+ unsigned long flags;
+
+ if (event->hw.idx < 0 || !event->hw.sample_period)
+ return;
+ local_irq_save(flags);
+ perf_disable();
+ fsl_emb_pmu_read(event);
+ left = event->hw.sample_period;
+ event->hw.last_period = left;
+ val = 0;
+ if (left < 0x80000000L)
+ val = 0x80000000L - left;
+ write_pmc(event->hw.idx, val);
+ atomic64_set(&event->hw.prev_count, val);
+ atomic64_set(&event->hw.period_left, left);
+ perf_event_update_userpage(event);
+ perf_enable();
+ local_irq_restore(flags);
+}
+
+static struct pmu fsl_emb_pmu = {
+ .enable = fsl_emb_pmu_enable,
+ .disable = fsl_emb_pmu_disable,
+ .read = fsl_emb_pmu_read,
+ .unthrottle = fsl_emb_pmu_unthrottle,
+};
+
+/*
+ * Release the PMU if this is the last perf_event.
+ */
+static void hw_perf_event_destroy(struct perf_event *event)
+{
+ if (!atomic_add_unless(&num_events, -1, 1)) {
+ mutex_lock(&pmc_reserve_mutex);
+ if (atomic_dec_return(&num_events) == 0)
+ release_pmc_hardware();
+ mutex_unlock(&pmc_reserve_mutex);
+ }
+}
+
+/*
+ * Translate a generic cache event_id config to a raw event_id code.
+ */
+static int hw_perf_cache_event(u64 config, u64 *eventp)
+{
+ unsigned long type, op, result;
+ int ev;
+
+ if (!ppmu->cache_events)
+ return -EINVAL;
+
+ /* unpack config */
+ type = config & 0xff;
+ op = (config >> 8) & 0xff;
+ result = (config >> 16) & 0xff;
+
+ if (type >= PERF_COUNT_HW_CACHE_MAX ||
+ op >= PERF_COUNT_HW_CACHE_OP_MAX ||
+ result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+ return -EINVAL;
+
+ ev = (*ppmu->cache_events)[type][op][result];
+ if (ev == 0)
+ return -EOPNOTSUPP;
+ if (ev == -1)
+ return -EINVAL;
+ *eventp = ev;
+ return 0;
+}
+
+const struct pmu *hw_perf_event_init(struct perf_event *event)
+{
+ u64 ev;
+ struct perf_event *events[MAX_HWEVENTS];
+ int n;
+ int err;
+ int num_restricted;
+ int i;
+
+ switch (event->attr.type) {
+ case PERF_TYPE_HARDWARE:
+ ev = event->attr.config;
+ if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
+ return ERR_PTR(-EOPNOTSUPP);
+ ev = ppmu->generic_events[ev];
+ break;
+
+ case PERF_TYPE_HW_CACHE:
+ err = hw_perf_cache_event(event->attr.config, &ev);
+ if (err)
+ return ERR_PTR(err);
+ break;
+
+ case PERF_TYPE_RAW:
+ ev = event->attr.config;
+ break;
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ event->hw.config = ppmu->xlate_event(ev);
+ if (!(event->hw.config & FSL_EMB_EVENT_VALID))
+ return ERR_PTR(-EINVAL);
+
+ /*
+ * If this is in a group, check if it can go on with all the
+ * other hardware events in the group. We assume the event
+ * hasn't been linked into its leader's sibling list at this point.
+ */
+ n = 0;
+ if (event->group_leader != event) {
+ n = collect_events(event->group_leader,
+ ppmu->n_counter - 1, events);
+ if (n < 0)
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) {
+ num_restricted = 0;
+ for (i = 0; i < n; i++) {
+ if (events[i]->hw.config & FSL_EMB_EVENT_RESTRICTED)
+ num_restricted++;
+ }
+
+ if (num_restricted >= ppmu->n_restricted)
+ return ERR_PTR(-EINVAL);
+ }
+
+ event->hw.idx = -1;
+
+ event->hw.config_base = PMLCA_CE | PMLCA_FCM1 |
+ (u32)((ev << 16) & PMLCA_EVENT_MASK);
+
+ if (event->attr.exclude_user)
+ event->hw.config_base |= PMLCA_FCU;
+ if (event->attr.exclude_kernel)
+ event->hw.config_base |= PMLCA_FCS;
+ if (event->attr.exclude_idle)
+ return ERR_PTR(-ENOTSUPP);
+
+ event->hw.last_period = event->hw.sample_period;
+ atomic64_set(&event->hw.period_left, event->hw.last_period);
+
+ /*
+ * See if we need to reserve the PMU.
+ * If no events are currently in use, then we have to take a
+ * mutex to ensure that we don't race with another task doing
+ * reserve_pmc_hardware or release_pmc_hardware.
+ */
+ err = 0;
+ if (!atomic_inc_not_zero(&num_events)) {
+ mutex_lock(&pmc_reserve_mutex);
+ if (atomic_read(&num_events) == 0 &&
+ reserve_pmc_hardware(perf_event_interrupt))
+ err = -EBUSY;
+ else
+ atomic_inc(&num_events);
+ mutex_unlock(&pmc_reserve_mutex);
+
+ mtpmr(PMRN_PMGC0, PMGC0_FAC);
+ isync();
+ }
+ event->destroy = hw_perf_event_destroy;
+
+ if (err)
+ return ERR_PTR(err);
+ return &fsl_emb_pmu;
+}
+
+/*
+ * A counter has overflowed; update its count and record
+ * things if requested. Note that interrupts are hard-disabled
+ * here so there is no possibility of being interrupted.
+ */
+static void record_and_restart(struct perf_event *event, unsigned long val,
+ struct pt_regs *regs, int nmi)
+{
+ u64 period = event->hw.sample_period;
+ s64 prev, delta, left;
+ int record = 0;
+
+ /* we don't have to worry about interrupts here */
+ prev = atomic64_read(&event->hw.prev_count);
+ delta = (val - prev) & 0xfffffffful;
+ atomic64_add(delta, &event->count);
+
+ /*
+ * See if the total period for this event has expired,
+ * and update for the next period.
+ */
+ val = 0;
+ left = atomic64_read(&event->hw.period_left) - delta;
+ if (period) {
+ if (left <= 0) {
+ left += period;
+ if (left <= 0)
+ left = period;
+ record = 1;
+ }
+ if (left < 0x80000000LL)
+ val = 0x80000000LL - left;
+ }
+
+ /*
+ * Finally record data if requested.
+ */
+ if (record) {
+ struct perf_sample_data data = {
+ .period = event->hw.last_period,
+ };
+
+ if (perf_event_overflow(event, nmi, &data, regs)) {
+ /*
+ * Interrupts are coming too fast - throttle them
+ * by setting the event to 0, so it will be
+ * at least 2^30 cycles until the next interrupt
+ * (assuming each event counts at most 2 counts
+ * per cycle).
+ */
+ val = 0;
+ left = ~0ULL >> 1;
+ }
+ }
+
+ write_pmc(event->hw.idx, val);
+ atomic64_set(&event->hw.prev_count, val);
+ atomic64_set(&event->hw.period_left, left);
+ perf_event_update_userpage(event);
+}
+
+static void perf_event_interrupt(struct pt_regs *regs)
+{
+ int i;
+ struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
+ struct perf_event *event;
+ unsigned long val;
+ int found = 0;
+ int nmi;
+
+ nmi = perf_intr_is_nmi(regs);
+ if (nmi)
+ nmi_enter();
+ else
+ irq_enter();
+
+ for (i = 0; i < ppmu->n_counter; ++i) {
+ event = cpuhw->event[i];
+
+ val = read_pmc(i);
+ if ((int)val < 0) {
+ if (event) {
+ /* event has overflowed */
+ found = 1;
+ record_and_restart(event, val, regs, nmi);
+ } else {
+ /*
+ * Disabled counter is negative,
+ * reset it just in case.
+ */
+ write_pmc(i, 0);
+ }
+ }
+ }
+
+ /* PMM will keep counters frozen until we return from the interrupt. */
+ mtmsr(mfmsr() | MSR_PMM);
+ mtpmr(PMRN_PMGC0, PMGC0_PMIE | PMGC0_FCECE);
+ isync();
+
+ if (nmi)
+ nmi_exit();
+ else
+ irq_exit();
+}
+
+void hw_perf_event_setup(int cpu)
+{
+ struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu);
+
+ memset(cpuhw, 0, sizeof(*cpuhw));
+}
+
+int register_fsl_emb_pmu(struct fsl_emb_pmu *pmu)
+{
+ if (ppmu)
+ return -EBUSY; /* something's already registered */
+
+ ppmu = pmu;
+ pr_info("%s performance monitor hardware support registered\n",
+ pmu->name);
+
+ return 0;
+}
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index fa0f690..a8aae0b 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -144,6 +144,16 @@ config FSL_EMB_PERFMON
and some e300 cores (c3 and c4). Select this only if your
core supports the Embedded Performance Monitor APU
+config FSL_EMB_PERF_EVENT
+ bool
+ depends on FSL_EMB_PERFMON && PERF_EVENTS && !PPC_PERF_CTRS
+ default y
+
+config FSL_EMB_PERF_EVENT_E500
+ bool
+ depends on FSL_EMB_PERF_EVENT && E500
+ default y
+
config 4xx
bool
depends on 40x || 44x
--
1.6.4.4
^ permalink raw reply related
* Re: [PATCH 1/2] perf_event: Build callchain code regardless of hardware event support.
From: Paul Mackerras @ 2010-02-26 0:09 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20100226000433.GA17033@loki.buserror.net>
On Thu, Feb 25, 2010 at 06:04:33PM -0600, Scott Wood wrote:
> It's also useful for software events, as well as future support for
> other types of hardware counters.
>
> Signed-off-by: Scott Wood <scottwood@freescale.com>
Acked-by: Paul Mackerras <paulus@samba.org>
^ permalink raw reply
* [PATCH 1/2] perf_event: Build callchain code regardless of hardware event support.
From: Scott Wood @ 2010-02-26 0:04 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
It's also useful for software events, as well as future support for
other types of hardware counters.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
arch/powerpc/kernel/Makefile | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index c002b04..93fd162 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -98,7 +98,8 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
-obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o perf_callchain.o
+obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
+obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o
obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \
power5+-pmu.o power6-pmu.o power7-pmu.o
obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o
--
1.6.4.4
^ permalink raw reply related
* Re: PCI on 834x
From: Scott Wood @ 2010-02-25 23:49 UTC (permalink / raw)
To: Gary Thomas; +Cc: linuxppc-dev, avorontsov
In-Reply-To: <4B870B17.7080701@mlbassoc.com>
Gary Thomas wrote:
> On 02/25/2010 02:24 PM, Scott Wood wrote:
>> Gary Thomas wrote:
>>> On 02/25/2010 02:03 PM, Scott Wood wrote:
>>>> Gary, can you check that the MMIO addresses are going to the PCI bus
>>>> as-is, and aren't being translated down to zero? I.e. POTARn should
>>>> equal POBARn, and likewise in the device
>>>> tree's pci node's ranges.
>>>
>>> Hmm, that doesn't match with how I've always had this setup. I have:
>>> POTAR0 = 0x00000000
>>> POTBR0 = 0x000C0000 (0xC0000000 >> 12)
>>>
>>> My device tree mappings are:
>>> ranges = <0x02000000 0x0 0xC0000000 0xC0000000 0x0 0x10000000
>>> 0x01000000 0x0 0x00000000 0xB8000000 0x0 0x00100000>
>>
>> That ranges property says that host address 0xc0000000 maps to PCI
>> address 0xc0000000, so Linux will program the BAR to 0xc0000000, but
>> the actual accesses will go elsewhere
>> because POTAR0 is zero.
>>
>> Setting POTAR to zero is also a bad idea because it's aliasing your
>> DMA window (it may work in certain situations based on who's
>> initiating the transaction, but it seems like it's
>> asking for trouble), plus it seems some cards just don't like address
>> zero.
>>
>> Try setting POTAR0 to 0x000c0000 and see what happens.
>
> Sadly, that doesn't work at all - neither RedBoot nor Linux
> can talk to any of the PCI devices.
Make sure that whatever is doing the PCI enumeration is allocating MMIO
addresses starting at 0xc0000000. That anything worked at all before
indicates that something was probably allocating from zero, despite
what's in the device tree.
-Scott
^ permalink raw reply
* Re: PCI on 834x
From: Gary Thomas @ 2010-02-25 23:43 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, avorontsov
In-Reply-To: <4B86EAA3.8000301@freescale.com>
On 02/25/2010 02:24 PM, Scott Wood wrote:
> Gary Thomas wrote:
>> On 02/25/2010 02:03 PM, Scott Wood wrote:
>>> Gary, can you check that the MMIO addresses are going to the PCI bus as-is, and aren't being translated down to zero? I.e. POTARn should equal POBARn, and likewise in the device
>>> tree's pci node's ranges.
>>
>> Hmm, that doesn't match with how I've always had this setup. I have:
>> POTAR0 = 0x00000000
>> POTBR0 = 0x000C0000 (0xC0000000 >> 12)
>>
>> My device tree mappings are:
>> ranges = <0x02000000 0x0 0xC0000000 0xC0000000 0x0 0x10000000
>> 0x01000000 0x0 0x00000000 0xB8000000 0x0 0x00100000>
>
> That ranges property says that host address 0xc0000000 maps to PCI address 0xc0000000, so Linux will program the BAR to 0xc0000000, but the actual accesses will go elsewhere
> because POTAR0 is zero.
>
> Setting POTAR to zero is also a bad idea because it's aliasing your DMA window (it may work in certain situations based on who's initiating the transaction, but it seems like it's
> asking for trouble), plus it seems some cards just don't like address zero.
>
> Try setting POTAR0 to 0x000c0000 and see what happens.
Sadly, that doesn't work at all - neither RedBoot nor Linux
can talk to any of the PCI devices.
--
------------------------------------------------------------
Gary Thomas | Consulting for the
MLB Associates | Embedded world
------------------------------------------------------------
^ permalink raw reply
* Re: PCI on 834x
From: Benjamin Herrenschmidt @ 2010-02-25 22:36 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, avorontsov, Gary Thomas
In-Reply-To: <4B86E5A7.9090607@freescale.com>
On Thu, 2010-02-25 at 15:03 -0600, Scott Wood wrote:
>
> It can, but I don't see how that would help, if the problem is that the
> video card doesn't like the low 30 bits of its MMIO address being zero.
My idea was the video card, if it's an old piece of shit, may not be
decoding all address bits.
> Gary, can you check that the MMIO addresses are going to the PCI bus
> as-is, and aren't being translated down to zero? I.e. POTARn should
> equal POBARn, and likewise in the device tree's pci node's ranges.
Cheers,
Ben.
^ permalink raw reply
* Re: PCI on 834x
From: Scott Wood @ 2010-02-25 21:24 UTC (permalink / raw)
To: Gary Thomas; +Cc: avorontsov, linuxppc-dev
In-Reply-To: <4B86E794.6020403@mlbassoc.com>
Gary Thomas wrote:
> On 02/25/2010 02:03 PM, Scott Wood wrote:
>> Gary, can you check that the MMIO addresses are going to the PCI bus
>> as-is, and aren't being translated down to zero? I.e. POTARn should
>> equal POBARn, and likewise in the device
>> tree's pci node's ranges.
>
> Hmm, that doesn't match with how I've always had this setup. I have:
> POTAR0 = 0x00000000
> POTBR0 = 0x000C0000 (0xC0000000 >> 12)
>
> My device tree mappings are:
> ranges = <0x02000000 0x0 0xC0000000 0xC0000000 0x0 0x10000000
> 0x01000000 0x0 0x00000000 0xB8000000 0x0 0x00100000>
That ranges property says that host address 0xc0000000 maps to PCI
address 0xc0000000, so Linux will program the BAR to 0xc0000000, but the
actual accesses will go elsewhere because POTAR0 is zero.
Setting POTAR to zero is also a bad idea because it's aliasing your DMA
window (it may work in certain situations based on who's initiating the
transaction, but it seems like it's asking for trouble), plus it seems
some cards just don't like address zero.
Try setting POTAR0 to 0x000c0000 and see what happens.
-Scott
^ permalink raw reply
* Re: PCI on 834x
From: Gary Thomas @ 2010-02-25 21:11 UTC (permalink / raw)
To: Scott Wood; +Cc: avorontsov, linuxppc-dev
In-Reply-To: <4B86E5A7.9090607@freescale.com>
On 02/25/2010 02:03 PM, Scott Wood wrote:
> Benjamin Herrenschmidt wrote:
>> On Thu, 2010-02-25 at 07:25 -0700, Gary Thomas wrote:
>>> I may have been too hasty pronouncing this fixed. Indeed, the
>>> SATA interface now works, but my video card (Fujitsu Coral-P)
>>> does not work when it's mapped at the bottom of the PCI space :-(
>>>
>>> With the bridge mapped, the video ends up at a non-zero address
>>> (0xC8000000..0xCFFFFFFF). If it gets mapped to 0xC0000000, it
>>> fails to respond to MMIO accesses.
>>>
>>> Any ideas how I might get around this? Is there a way to force
>>> the PCI allocator to start somewhere other than [relative] zero?
>>
>> I'm not familiar with the way the FSL bridge works, but it would
>> be possible to invert MMIO and DMA on your PCI bus. IE. Have MMIO go
>> from 0....2G and DMA from 2G..4G for example. Provided the FSL bridge
>> can offset the DMA back down to 0 (memory). Can it ?
>
> It can, but I don't see how that would help, if the problem is that the video card doesn't like the low 30 bits of its MMIO address being zero.
>
> Gary, can you check that the MMIO addresses are going to the PCI bus as-is, and aren't being translated down to zero? I.e. POTARn should equal POBARn, and likewise in the device
> tree's pci node's ranges.
Hmm, that doesn't match with how I've always had this setup. I have:
POTAR0 = 0x00000000
POTBR0 = 0x000C0000 (0xC0000000 >> 12)
My device tree mappings are:
ranges = <0x02000000 0x0 0xC0000000 0xC0000000 0x0 0x10000000
0x01000000 0x0 0x00000000 0xB8000000 0x0 0x00100000>
n.b. I don't run U-Boot on these platforms (being the author
of RedBoot and all... :-)
--
------------------------------------------------------------
Gary Thomas | Consulting for the
MLB Associates | Embedded world
------------------------------------------------------------
^ permalink raw reply
* Re: PCI on 834x
From: Scott Wood @ 2010-02-25 21:03 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, avorontsov, Gary Thomas
In-Reply-To: <1267130982.23523.1728.camel@pasglop>
Benjamin Herrenschmidt wrote:
> On Thu, 2010-02-25 at 07:25 -0700, Gary Thomas wrote:
>> I may have been too hasty pronouncing this fixed. Indeed, the
>> SATA interface now works, but my video card (Fujitsu Coral-P)
>> does not work when it's mapped at the bottom of the PCI space :-(
>>
>> With the bridge mapped, the video ends up at a non-zero address
>> (0xC8000000..0xCFFFFFFF). If it gets mapped to 0xC0000000, it
>> fails to respond to MMIO accesses.
>>
>> Any ideas how I might get around this? Is there a way to force
>> the PCI allocator to start somewhere other than [relative] zero?
>
> I'm not familiar with the way the FSL bridge works, but it would
> be possible to invert MMIO and DMA on your PCI bus. IE. Have MMIO go
> from 0....2G and DMA from 2G..4G for example. Provided the FSL bridge
> can offset the DMA back down to 0 (memory). Can it ?
It can, but I don't see how that would help, if the problem is that the
video card doesn't like the low 30 bits of its MMIO address being zero.
Gary, can you check that the MMIO addresses are going to the PCI bus
as-is, and aren't being translated down to zero? I.e. POTARn should
equal POBARn, and likewise in the device tree's pci node's ranges.
-Scott
^ permalink raw reply
* Re: [PATCH 3/7] RapidIO: Add Port-Write handling for EM
From: Micha Nelissen @ 2010-02-25 21:02 UTC (permalink / raw)
To: Bounine, Alexandre
Cc: Alexandre Bounine, linux-kernel, thomas.moll, linuxppc-dev,
thomas.moll.ext
In-Reply-To: <0CE8B6BE3C4AD74AB97D9D29BD24E552A5508A@CORPEXCH1.na.ads.idt.com>
Bounine, Alexandre wrote:
> Micha Nelissen wrote:
>> Alexandre Bounine wrote:
>>> /**
>>> + * rio_em_set_ops- Sets Error Managment operations for a particular
> vendor switch
>>> + * @rdev: RIO device
>>> + *
>>> + * Searches the RIO EM ops table for known switch types. If the vid
>>> + * and did match a switch table entry, then set the em_init() and
>>> + * em_handle() ops to the table entry values.
>> Shouldn't any RIO device be able to support error management, not just
>> switches?
>
> Only if a device reports this capability by having Error Management
> Extended Features block.
> Ideally, we have to provide default handler for every such device (I am
> planning it for some future updates). It should be the same as for
> routing operations - if the standard feature exists, it has to be used
> unless something else takes over.
Yes, therefore I thought that: or the EM_OPS are per driver, or they can
be integrated in the switch hooks list.
> For now I keep all port-write messages from end-points serviced by their
> individual drivers. One of reasons for this: the EM PW message format
Maybe have a generic rio function that can be called by any driver that
knows a particular port-write was due to error management causes? This
function would read the standard defined EF block registers. Then the
driver part can be quite small.
>>> + if (port->ops->pwenable)
>>> + port->ops->pwenable(port, enable);
>>> +}
>>> +
>> Maybe this can be done by switch->init function?
>
> This is not per-switch function. This function enables mport to receive
> incoming PW messages. Per-switch PW enable is done in switch->init as
> for Tsi57x.
Oops, I meant this comment for the em_init function call.
>>> + rio_mport_write_config_32(mport, destid,
> hopcount,
>>> + rdev->phys_efptr +
>>> + RIO_PORT_N_ACK_STS_CSR(portnum),
>>> + RIO_PORT_N_ACK_CLEAR);
>> This doesn't work for the 568; but the 568 has no special handling?
>
> Tsi568 will not send EM PW message. Tsi568 PWs are disabled in its
> em_init().
Why?
>>> +DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_em_init,
> tsi57x_em_handler);
>> Why not declare these along with the other ops?
>
> Because the EM extensions is a separate capability. It is not guaranteed
> to be in every switch.
They might initialize them with NULL to indicate they don't support it?
Micha
^ permalink raw reply
* Re: PCI on 834x
From: Benjamin Herrenschmidt @ 2010-02-25 20:49 UTC (permalink / raw)
To: Gary Thomas; +Cc: Scott Wood, linuxppc-dev, avorontsov
In-Reply-To: <4B86886B.5000304@mlbassoc.com>
On Thu, 2010-02-25 at 07:25 -0700, Gary Thomas wrote:
> I may have been too hasty pronouncing this fixed. Indeed, the
> SATA interface now works, but my video card (Fujitsu Coral-P)
> does not work when it's mapped at the bottom of the PCI space :-(
>
> With the bridge mapped, the video ends up at a non-zero address
> (0xC8000000..0xCFFFFFFF). If it gets mapped to 0xC0000000, it
> fails to respond to MMIO accesses.
>
> Any ideas how I might get around this? Is there a way to force
> the PCI allocator to start somewhere other than [relative] zero?
I'm not familiar with the way the FSL bridge works, but it would
be possible to invert MMIO and DMA on your PCI bus. IE. Have MMIO go
from 0....2G and DMA from 2G..4G for example. Provided the FSL bridge
can offset the DMA back down to 0 (memory). Can it ?
Cheers,
Ben.
^ permalink raw reply
* CONFIG_ISA_DMA_API without CONFIG_GENERIC_ISA_DMA
From: Scott Wood @ 2010-02-25 20:40 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev@ozlabs.org list
I tried building a kernel using mpc85xx_smp_defconfig, but with all
platforms but p4080ds removed. This was the result:
> LD .tmp_vmlinux1
> sound/built-in.o: In function `claim_dma_lock':
> /home/scott/git/fsl/linux/upstream/arch/powerpc/include/asm/dma.h:179: undefined reference to `dma_spin_lock'
> /home/scott/git/fsl/linux/upstream/arch/powerpc/include/asm/dma.h:179: undefined reference to `dma_spin_lock'
> /home/scott/git/fsl/linux/upstream/arch/powerpc/include/asm/dma.h:179: undefined reference to `dma_spin_lock'
> /home/scott/git/fsl/linux/upstream/arch/powerpc/include/asm/dma.h:179: undefined reference to `dma_spin_lock'
> /home/scott/git/fsl/linux/upstream/arch/powerpc/include/asm/dma.h:179: undefined reference to `dma_spin_lock'
> sound/built-in.o:/home/scott/git/fsl/linux/upstream/arch/powerpc/include/asm/dma.h:179: more undefined references to `dma_spin_lock' follow
> make: *** [.tmp_vmlinux1] Error 1
Commit fb4f0e8832e0075849b41b65f6bb9fdfa7593b99 (Enable GENERIC_ISA_DMA
if FSL_ULI1575 to fix compile issue) tries to deal with this, but it
ties it to CONFIG_FSL_ULI1575, which is not selected in a p4080ds-only
config.
It seems that ULI isn't really relevant to the actual problem, which is
that we enable ISA DMA API support without selecting an implementation.
Whether a certain chip is on the board that has an actual ISA
interface is irrelevant to the build breakage.
Where did the dependency list for GENERIC_ISA_DMA come from? Are there
any legitimate cases on powerpc where we want to select ISA_DMA_API but
not GENERIC_ISA_DMA (i.e. we have an alternate implementation)?
-Scott
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox