* Re: [Patch 1/1] PPC64-HWBKPT: Implement hw-breakpoints for PPC64
From: K.Prasad @ 2010-01-22 7:14 UTC (permalink / raw)
To: Roland McGrath
Cc: Michael Neuling, Benjamin Herrenschmidt, Frederic Weisbecker,
David Gibson, linuxppc-dev, Alan Stern, paulus
In-Reply-To: <20100119100335.3EB621DE@magilla.sf.frob.com>
On Tue, Jan 19, 2010 at 02:03:35AM -0800, Roland McGrath wrote:
> > It is also not clear to me if disabling pre-emption for the user-space
> > (albeit for a very tiny time-window) is incorrect and if their side-effects
> > are known. If otherwise, I think we should choose to operate in pre-empt
> > safe mode and avoid all costs associated when done without it.
>
> I never really gave much consideration to returning to user mode with
> preemption disabled. It would not really have occurred to me that was
> even possible. I can't say it seems to me like it could ever be a very
> good idea. I find it hard even to start listing the cans of worms that
> might be opened by that. Perhaps the powerpc maintainers have a clearer
> picture of it than I do.
>
> What does it mean when there is something that prevents it from returning
> to user mode? i.e., TIF_SIGPENDING or TIF_NEED_RESCHED, or whatever. It
> could do a lot in the kernel before it gets back to user mode. What if in
> there somewhere it blocks voluntarily?
>
> Similarly, what does it mean if you get to user mode but the single-stepped
> instruction is a load/store that gets a page fault? What if it blocks in
> the page fault handler?
>
> For that matter, what about a page fault for the kernel-mode case?
>
> Perhaps I'm imagining gremlins where there aren't any, but I just cannot
> really get my head around this "disable preemption while running some
> unknown instruction that normally runs with preemption enabled" thing--let
> alone "disable preemption while returning to user mode".
>
>
> Thanks,
> Roland
I posted a patch which re-enables pre-emption after a hw-breakpoint is
processed (linuxppc-dev ref: 20100121084640.GA3252@in.ibm.com). It does
lead to clumsiness (due to the new variables to track states, prior
breakpoints, etc.) but with the reasons you pointed out, it is much
better than having uncertain/incorrect code.
Thanks for your comments.
-- K.Prasad
^ permalink raw reply
* Re: Large physical address support on e500 platform
From: Aaron Pace @ 2010-01-22 6:27 UTC (permalink / raw)
To: linuxppc-dev
> >
> > Its possible that we've broken module/vmalloc support with
> > "Large physical addressing".? Its not something I've
> > tried in a while.? What kernel/git SHA are you using.
> >
>I'm just pulling in from the main kernel tree git.
>My current version is 2.6.33-rc4-00193-gd1e4922-dirty,
>but it had not changed since 2.6.33-rc2
>
>I started from 2.6.32, but I don't remember if I had a large PA
>support enabled there.
Just to second this issue, the following commit is what broke this:
[76acc2c1a7a9a8c2cae7e9cf8d0a8b374a48aa94]
I didn't have time to delve into the whys & hows, but this commit
caused the same issue on an 8572 platform.
Reverting this one change allows everything (including 36-bit memory
access) to work correctly, as before.
-Aaron Pace
^ permalink raw reply
* Re: [RFC/PATCH] powerpc: Dynamically allocate pacas
From: Michael Neuling @ 2010-01-22 3:19 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
In-Reply-To: <39fb8f1aeab9940b86c940b9a5f8e6bd41ec316c.1263368253.git.michael@ellerman.id.au>
In message <39fb8f1aeab9940b86c940b9a5f8e6bd41ec316c.1263368253.git.michael=
@ell
erman.id.au> you wrote:
> On 64-bit kernels we currently have a 512 byte struct paca_struct for
> each cpu (usually just called "the paca"). Currently they are statically
> allocated, which means a kernel built for a large number of cpus will
> waste a lot of space if it's booted on a machine with few cpus.
>=20
> We can avoid that by only allocating the number of pacas we need at
> boot. However this is complicated by the fact that we need to access
> the paca before we know how many cpus there are in the system.
>=20
> The solution is to dynamically allocate enough space for NR_CPUS pacas,
> but then later in boot when we know how many cpus we have, we free any
> unused pacas.
>=20
> Lightly booted on Legacy iSeries & pSeries LPAR.
This is broken on 32bit CPUs. Dies at compile time with
mpc86xx_defconfig. No paca on 32bit :-(
/home/mikey/src/linux-2.6-ozlabs/arch/powerpc/kernel/prom.c: In function =
=E2=80=98early_init_devtree=E2=80=99:
/home/mikey/src/linux-2.6-ozlabs/arch/powerpc/kernel/prom.c:1227: error: im=
plicit declaration of function =E2=80=98allocate_pacas=E2=80=99
make[2]: *** [arch/powerpc/kernel/prom.o] Error 1
make[2]: *** Waiting for unfinished jobs....
/home/mikey/src/linux-2.6-ozlabs/arch/powerpc/kernel/setup-common.c: In fun=
ction =E2=80=98smp_setup_cpu_maps=E2=80=99:
/home/mikey/src/linux-2.6-ozlabs/arch/powerpc/kernel/setup-common.c:497: er=
ror: implicit declaration of function =E2=80=98free_unused_pacas=E2=80=99
make[2]: *** [arch/powerpc/kernel/setup-common.o] Error 1
make[1]: *** [arch/powerpc/kernel] Error 2
make[1]: *** Waiting for unfinished jobs....
Mikey
>=20
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> ---
> arch/powerpc/include/asm/paca.h | 8 ++-
> arch/powerpc/kernel/head_64.S | 6 +-
> arch/powerpc/kernel/paca.c | 93 +++++++++++++++++++++-=
----
--
> arch/powerpc/kernel/prom.c | 2 +
> arch/powerpc/kernel/setup-common.c | 2 +
> arch/powerpc/kernel/setup_64.c | 12 ++--
> arch/powerpc/platforms/iseries/exception.S | 25 +++++---
> 7 files changed, 106 insertions(+), 42 deletions(-)
>=20
> diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/p=
aca.
h
> index 5e9b4ef..41e0f17 100644
> --- a/arch/powerpc/include/asm/paca.h
> +++ b/arch/powerpc/include/asm/paca.h
> @@ -14,6 +14,7 @@
> #define _ASM_POWERPC_PACA_H
> #ifdef __KERNEL__
>=20=20
> +#include <linux/init.h>
> #include <asm/types.h>
> #include <asm/lppaca.h>
> #include <asm/mmu.h>
> @@ -140,8 +141,11 @@ struct paca_struct {
> #endif
> };
>=20=20
> -extern struct paca_struct paca[];
> -extern void initialise_pacas(void);
> +extern struct paca_struct *paca;
> +extern __initdata struct paca_struct boot_paca;
> +extern void allocate_pacas(void);
> +extern void initialise_paca(struct paca_struct *new_paca, int cpu);
> +extern void free_unused_pacas(void);
>=20=20
> #endif /* __KERNEL__ */
> #endif /* _ASM_POWERPC_PACA_H */
> diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
> index 9258074..b24b700 100644
> --- a/arch/powerpc/kernel/head_64.S
> +++ b/arch/powerpc/kernel/head_64.S
> @@ -219,7 +219,8 @@ generic_secondary_common_init:
> * physical cpu id in r24, we need to search the pacas to find
> * which logical id maps to our physical one.
> */
> - LOAD_REG_ADDR(r13, paca) /* Get base vaddr of paca array */
> + LOAD_REG_ADDR(r13, paca) /* Load paca pointer */
> + ld r13,0(r13) /* Get base vaddr of paca array */
> li r5,0 /* logical cpu id */
> 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */
> cmpw r6,r24 /* Compare to our id */
> @@ -536,7 +537,8 @@ _GLOBAL(pmac_secondary_start)
> mtmsrd r3 /* RI on */
>=20=20
> /* Set up a paca value for this processor. */
> - LOAD_REG_ADDR(r4,paca) /* Get base vaddr of paca array */
> + LOAD_REG_ADDR(r4,paca) /* Load paca pointer */
> + ld r4,0(r4) /* Get base vaddr of paca array */
> mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */
> add r13,r13,r4 /* for this processor. */
> mtspr SPRN_SPRG_PACA,r13 /* Save vaddr of paca in an SPRG*/
> diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
> index d16b1ea..0c40c6f 100644
> --- a/arch/powerpc/kernel/paca.c
> +++ b/arch/powerpc/kernel/paca.c
> @@ -9,11 +9,15 @@
>=20=20
> #include <linux/threads.h>
> #include <linux/module.h>
> +#include <linux/lmb.h>
>=20=20
> +#include <asm/firmware.h>
> #include <asm/lppaca.h>
> #include <asm/paca.h>
> #include <asm/sections.h>
> #include <asm/pgtable.h>
> +#include <asm/iseries/lpar_map.h>
> +#include <asm/iseries/hv_types.h>
>=20=20
> /* This symbol is provided by the linker - let it fill in the paca
> * field correctly */
> @@ -70,37 +74,82 @@ struct slb_shadow slb_shadow[] __cacheline_aligned =
=3D {
> * processors. The processor VPD array needs one entry per physical
> * processor (not thread).
> */
> -struct paca_struct paca[NR_CPUS];
> +struct paca_struct *paca;
> EXPORT_SYMBOL(paca);
>=20=20
> -void __init initialise_pacas(void)
> -{
> - int cpu;
> +struct paca_struct boot_paca;
>=20=20
> - /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB
> - * of the TOC can be addressed using a single machine instruction.
> - */
> +void __init initialise_paca(struct paca_struct *new_paca, int cpu)
> +{
> + /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB
> + * of the TOC can be addressed using a single machine instruction.
> + */
> unsigned long kernel_toc =3D (unsigned long)(&__toc_start) + 0x8000UL;
>=20=20
> - /* Can't use for_each_*_cpu, as they aren't functional yet */
> - for (cpu =3D 0; cpu < NR_CPUS; cpu++) {
> - struct paca_struct *new_paca =3D &paca[cpu];
> -
> #ifdef CONFIG_PPC_BOOK3S
> - new_paca->lppaca_ptr =3D &lppaca[cpu];
> + new_paca->lppaca_ptr =3D &lppaca[cpu];
> #else
> - new_paca->kernel_pgd =3D swapper_pg_dir;
> + new_paca->kernel_pgd =3D swapper_pg_dir;
> #endif
> - new_paca->lock_token =3D 0x8000;
> - new_paca->paca_index =3D cpu;
> - new_paca->kernel_toc =3D kernel_toc;
> - new_paca->kernelbase =3D (unsigned long) _stext;
> - new_paca->kernel_msr =3D MSR_KERNEL;
> - new_paca->hw_cpu_id =3D 0xffff;
> - new_paca->__current =3D &init_task;
> + new_paca->lock_token =3D 0x8000;
> + new_paca->paca_index =3D cpu;
> + new_paca->kernel_toc =3D kernel_toc;
> + new_paca->kernelbase =3D (unsigned long) _stext;
> + new_paca->kernel_msr =3D MSR_KERNEL;
> + new_paca->hw_cpu_id =3D 0xffff;
> + new_paca->__current =3D &init_task;
> #ifdef CONFIG_PPC_STD_MMU_64
> - new_paca->slb_shadow_ptr =3D &slb_shadow[cpu];
> + new_paca->slb_shadow_ptr =3D &slb_shadow[cpu];
> #endif /* CONFIG_PPC_STD_MMU_64 */
> +}
> +
> +static int __initdata paca_size;
> +
> +void __init allocate_pacas(void)
> +{
> + int nr_cpus, cpu, limit;
> +
> + /*
> + * We can't take SLB misses on the paca, and we want to access them
> + * in real mode, so allocate them within the RMA and also within
> + * the first segment. On iSeries they must be within the area mapped
> + * by the HV, which is HvPagesToMap * HVPAGESIZE bytes.
> + */
> + limit =3D min(0x10000000ULL, lmb.rmo_size);
> + if (firmware_has_feature(FW_FEATURE_ISERIES))
> + limit =3D min(limit, HvPagesToMap * HVPAGESIZE);
> +
> + nr_cpus =3D NR_CPUS;
> + /* On iSeries we know we can never have more than 64 cpus */
> + if (firmware_has_feature(FW_FEATURE_ISERIES))
> + nr_cpus =3D min(64, nr_cpus);
> +
> + paca_size =3D PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpus);
> +
> + paca =3D __va(lmb_alloc_base(paca_size, PAGE_SIZE, limit));
> + memset(paca, 0, paca_size);
> +
> + printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p\n",
> + paca_size, nr_cpus, paca);
> +
> + /* Can't use for_each_*_cpu, as they aren't functional yet */
> + for (cpu =3D 0; cpu < nr_cpus; cpu++)
> + initialise_paca(&paca[cpu], cpu);
> +}
> +
> +void __init free_unused_pacas(void)
> +{
> + int new_size;
> +
> + new_size =3D PAGE_ALIGN(sizeof(struct paca_struct) * num_possible_cpus(=
))
;
> +
> + if (new_size >=3D paca_size)
> + return;
> +
> + lmb_free(__pa(paca) + new_size, paca_size - new_size);
> +
> + printk(KERN_DEBUG "Freed %u bytes for unused pacas\n",
> + paca_size - new_size);
>=20=20
> - }
> + paca_size =3D new_size;
> }
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index 4ec3008..50c3c55 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -1224,6 +1224,8 @@ void __init early_init_devtree(void *params)
> * FIXME .. and the initrd too? */
> move_device_tree();
>=20=20
> + allocate_pacas();
> +
> DBG("Scanning CPUs ...\n");
>=20=20
> /* Retreive CPU related informations from the flat tree
> diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/set=
up-c
ommon.c
> index 03dd6a2..5df0f6a 100644
> --- a/arch/powerpc/kernel/setup-common.c
> +++ b/arch/powerpc/kernel/setup-common.c
> @@ -493,6 +493,8 @@ void __init smp_setup_cpu_maps(void)
> * here will have to be reworked
> */
> cpu_init_thread_core_maps(nthreads);
> +
> + free_unused_pacas();
> }
> #endif /* CONFIG_SMP */
>=20=20
> diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_6=
4.c
> index 6568406..6354739 100644
> --- a/arch/powerpc/kernel/setup_64.c
> +++ b/arch/powerpc/kernel/setup_64.c
> @@ -144,9 +144,9 @@ early_param("smt-enabled", early_smt_enabled);
> #endif /* CONFIG_SMP */
>=20=20
> /* Put the paca pointer into r13 and SPRG_PACA */
> -void __init setup_paca(int cpu)
> +static void __init setup_paca(struct paca_struct *new_paca)
> {
> - local_paca =3D &paca[cpu];
> + local_paca =3D new_paca;
> mtspr(SPRN_SPRG_PACA, local_paca);
> #ifdef CONFIG_PPC_BOOK3E
> mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb);
> @@ -176,14 +176,12 @@ void __init early_setup(unsigned long dt_ptr)
> {
> /* -------- printk is _NOT_ safe to use here ! ------- */
>=20=20
> - /* Fill in any unititialised pacas */
> - initialise_pacas();
> -
> /* Identify CPU type */
> identify_cpu(0, mfspr(SPRN_PVR));
>=20=20
> /* Assume we're on cpu 0 for now. Don't write to the paca yet! */
> - setup_paca(0);
> + initialise_paca(&boot_paca, 0);
> + setup_paca(&boot_paca);
>=20=20
> /* Initialize lockdep early or else spinlocks will blow */
> lockdep_init();
> @@ -203,7 +201,7 @@ void __init early_setup(unsigned long dt_ptr)
> early_init_devtree(__va(dt_ptr));
>=20=20
> /* Now we know the logical id of our boot cpu, setup the paca. */
> - setup_paca(boot_cpuid);
> + setup_paca(&paca[boot_cpuid]);
>=20=20
> /* Fix up paca fields required for the boot cpu */
> get_paca()->cpu_start =3D 1;
> diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/pl=
atfo
rms/iseries/exception.S
> index 5369653..fba5bf9 100644
> --- a/arch/powerpc/platforms/iseries/exception.S
> +++ b/arch/powerpc/platforms/iseries/exception.S
> @@ -43,17 +43,14 @@ system_reset_iSeries:
> LOAD_REG_ADDR(r23, alpaca)
> li r0,ALPACA_SIZE
> sub r23,r13,r23
> - divdu r23,r23,r0 /* r23 has cpu number */
> - LOAD_REG_ADDR(r13, paca)
> - mulli r0,r23,PACA_SIZE
> - add r13,r13,r0
> - mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */
> - mfmsr r24
> - ori r24,r24,MSR_RI
> - mtmsrd r24 /* RI on */
> - mr r24,r23
> + divdu r24,r23,r0 /* r24 has cpu number */
> cmpwi 0,r24,0 /* Are we processor 0? */
> bne 1f
> + LOAD_REG_ADDR(r13, boot_paca)
> + mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */
> + mfmsr r23
> + ori r23,r23,MSR_RI
> + mtmsrd r23 /* RI on */
> b .__start_initialization_iSeries /* Start up the first processor
*/
> 1: mfspr r4,SPRN_CTRLF
> li r5,CTRL_RUNLATCH /* Turn off the run light */
> @@ -86,6 +83,16 @@ system_reset_iSeries:
> #endif
>=20=20
> 2:
> + /* Load our paca now that it's been allocated */
> + LOAD_REG_ADDR(r13, paca)
> + ld r13,0(r13)
> + mulli r0,r24,PACA_SIZE
> + add r13,r13,r0
> + mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */
> + mfmsr r23
> + ori r23,r23,MSR_RI
> + mtmsrd r23 /* RI on */
> +
> HMT_LOW
> #ifdef CONFIG_SMP
> lbz r23,PACAPROCSTART(r13) /* Test if this processor
> --=20
> 1.6.3.3
>=20
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>=20
^ permalink raw reply
* Re: mount ramdisk rootfs /etc directory to jffs2 filesystem.
From: Johnny Hung @ 2010-01-22 3:07 UTC (permalink / raw)
To: Marco Stornelli
Cc: Ricard Wanderlof, linux-embedded@vger.kernel.org, kernelnewbies,
linux-mtd@lists.infradead.org, Matthias Kaehlcke,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <2ea1731b1001192357r72d627e2gb36d71f23fd69b2e@mail.gmail.com>
2010/1/20 Marco Stornelli <marco.stornelli@gmail.com>:
> 2010/1/20 Johnny Hung <johnny.hacking@gmail.com>:
>> 2010/1/19 Matthias Kaehlcke <matthias@kaehlcke.net>:
>>> El Tue, Jan 19, 2010 at 02:17:22PM +0100 Ricard Wanderlof ha dit:
>>>
>> I consider to use ramdisk as rootfs because worry about wrong
>> operation in rootfs (is use jffs2 rootfs) and it will cause system
>> boot up failed.
>> Another query, does the syslogd/klogd log files also store in jffs2
>> rootfs? Write to jffs2 frequently will reduce flash life cycle.
>>
>> BRs, H. Johnny
>>>
>>> --
>
It seems there are a lot of file-systems I have to study :P. The same
question is
how to split my rootfs? Re-mount /etc, /var to another file-sysyem mtd part when
system boot up?
Thank your good advice.
BRs, H. Johnny
> In general a good splitting for rootfs could be: squashfs for rootfs,
> tmpfs for volatile data (/tmp), ubifs (with a flash partition) for
> "strong" permanent data (/etc, ....) and pramfs for "light" permanent
> data (/var/log, .....).
> I think you should "split" your rootfs. Ramdisk is an old approach
> with some drawbacks.
>
> Marco
>
^ permalink raw reply
* Re: mount ramdisk rootfs /etc directory to jffs2 filesystem.
From: Johnny Hung @ 2010-01-22 3:01 UTC (permalink / raw)
To: Ricard Wanderlof
Cc: kernelnewbies, linuxppc-dev@lists.ozlabs.org,
linux-mtd@lists.infradead.org, linux-embedded@vger.kernel.org,
Matthias Kaehlcke
In-Reply-To: <Pine.LNX.4.64.1001200809550.32263@lnxricardw.se.axis.com>
2010/1/20 Ricard Wanderlof <ricard.wanderlof@axis.com>:
>
> On Wed, 20 Jan 2010, Johnny Hung wrote:
>
>>> i'd also recommend you to consider if you really need the
>>> ramdisk. when using a ram disk its entire content is loaded to the RAM
>>> occupying space, even if you don't use certain files (or part of
>>> them). other filesystems are more efficient in this aspect.
>>> if the main purpose is to have a read only rootfs, i'd suggest a look
>>> at squashfs.
>>
>> I consider to use ramdisk as rootfs because worry about wrong
>> operation in rootfs (is use jffs2 rootfs) and it will cause system
>> boot up failed.
>
> You have a point, however, you could do two things to help:
>
> a) Mount the root file system as read-only. That way you can never write =
to
> it, unless you remount it read-write. But you can still reflash that
> partition if you need to upgrade.
>
> b) Register the mtd partition holding the root file system as read-only.
> This is even more seecure as remounting the file system won't permit writ=
es.
> However, it also means you can't write to it for upgrading. (I
> don't think the mtd core permits changing an already registered mtd
> partition from readonly to writable, but I could be wrong.)
>
>> Another query, does the syslogd/klogd log files also store in jffs2
>> rootfs? Write to jffs2 frequently will reduce flash life cycle.
>
> I think it is fairly common to have a combination of devices:
>
> / (root) =A0 =A0 =A0 =A0is a readonly flash device (mtd partition)
> /etc =A0 =A0 =A0 =A0 =A0 =A0is a writable flash device (mtd partition)
> /tmp and /var =A0 are ramdisks (tmpfs), so they are writable, but lost wh=
en
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0power is cycled.
I think it's a good combination for my board. How do I sepcific the
/etc to another mtd part?
The busybox init will parse /etc/inittab after setup signal handler
and initializes console. I only
know to do it is to re-mount etc directory from another mtd to /etc.
Is it right?
Thank your help.
BRs, H. Johnny
>
> /Ricard
> --
> Ricard Wolf Wanderl=F6f =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 ricardw(at)axis.com
> Axis Communications AB, Lund, Sweden =A0 =A0 =A0 =A0 =A0 =A0www.axis.com
> Phone +46 46 272 2016 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
Fax +46 46 13 61 30
>
^ permalink raw reply
* Re: [net-next-2.6 PATCH 2/3] fs_enet: Add support for MPC512x to fs_enet driver
From: David Miller @ 2010-01-22 2:03 UTC (permalink / raw)
To: wg; +Cc: wd, dzu, netdev, linuxppc-dev, agust, kosmo
In-Reply-To: <4B5871F2.9090005@grandegger.com>
From: Wolfgang Grandegger <wg@grandegger.com>
Date: Thu, 21 Jan 2010 16:25:38 +0100
> Do you see a more clever solution to this problem?
See how we handle this in the ESP scsi driver. We have a set of
defines for the register offsets, and a set of methods a chip driver
implements for register accesses.
If the offsets differ, the register access method can translate the
generic register offsets into whatever layout their implementation
actually uses.
> Nevertheless, the code could be improved by using "offsetof", I
> think.
At a minimum :-)
^ permalink raw reply
* Re: [PATCH] powerpc/85xx: Fix SMP when "cpu-release-addr" is in lowmem
From: Peter Tyser @ 2010-01-21 22:28 UTC (permalink / raw)
To: linuxppc-dev; +Cc: kumar.gala, Nate Case
In-Reply-To: <1261176637-23912-1-git-send-email-ptyser@xes-inc.com>
On Fri, 2009-12-18 at 16:50 -0600, Peter Tyser wrote:
> Recent U-Boot commit 5ccd29c3679b3669b0bde5c501c1aa0f325a7acb caused
> the "cpu-release-addr" device tree property to contain the physical RAM
> location that secondary cores were spinning at. Previously, the
> "cpu-release-addr" property contained a value referencing the boot page
> translation address range of 0xfffffxxx, which then indirectly accessed
> RAM.
>
> The "cpu-release-addr" is currently ioremapped and the secondary cores
> kicked. However, due to the recent change in "cpu-release-addr", it
> sometimes points to a memory location in low memory that cannot be
> ioremapped. For example on a P2020-based board with 512MB of RAM the
> following error occurs on bootup:
>
> <...>
> mpic: requesting IPIs ...
> __ioremap(): phys addr 0x1ffff000 is RAM lr c05df9a0
> Unable to handle kernel paging request for data at address 0x00000014
> Faulting instruction address: 0xc05df9b0
> Oops: Kernel access of bad area, sig: 11 [#1]
> SMP NR_CPUS=2 P2020 RDB
> Modules linked in:
> <... eventual kernel panic>
>
> Adding logic to conditionally ioremap or access memory directly resolves
> the issue.
>
> Signed-off-by: Peter Tyser <ptyser@xes-inc.com>
> Signed-off-by: Nate Case <ncase@xes-inc.com>
> Reported-by: Dipen Dudhat <B09055@freescale.com>
> Tested-by: Dipen Dudhat <B09055@freescale.com>
Any chance this going to be picked up for 2.6.33? The issue is
currently going to bite anyone using an MP-capable 85xx system that
doesn't use highmem.
Thanks,
Peter
^ permalink raw reply
* Re: [net-next-2.6 PATCH 2/3] fs_enet: Add support for MPC512x to fs_enet driver
From: Wolfgang Grandegger @ 2010-01-21 20:15 UTC (permalink / raw)
To: Anatolij Gustschin; +Cc: wd, dzu, netdev, linuxppc-dev, Piotr Ziecik
In-Reply-To: <1264039999-25731-3-git-send-email-agust@denx.de>
Hi Anatolij,
I had a close look...
Anatolij Gustschin wrote:
> drivers/net/fs_enet/*
> Enable fs_enet driver to work 5121 FEC
> Enable it with CONFIG_FS_ENET_MPC5121_FEC
>
> Signed-off-by: John Rigby <jcrigby@gmail.com>
> Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
> Signed-off-by: Wolfgang Denk <wd@denx.de>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: <linuxppc-dev@ozlabs.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> ---
> Changes since previous submited version:
>
> - explicit type usage in register tables.
> - don't use same variable name "fecp" for variables of
> different types.
> - avoid re-checking the compatible by passing data pointer
> in the match struct.
>
> drivers/net/fs_enet/Kconfig | 10 +-
> drivers/net/fs_enet/fs_enet-main.c | 4 +
> drivers/net/fs_enet/fs_enet.h | 40 +++++++-
> drivers/net/fs_enet/mac-fec.c | 212 +++++++++++++++++++++++++-----------
> drivers/net/fs_enet/mii-fec.c | 76 ++++++++++---
> drivers/net/fs_enet/mpc5121_fec.h | 64 +++++++++++
> drivers/net/fs_enet/mpc8xx_fec.h | 37 ++++++
> 7 files changed, 356 insertions(+), 87 deletions(-)
> create mode 100644 drivers/net/fs_enet/mpc5121_fec.h
> create mode 100644 drivers/net/fs_enet/mpc8xx_fec.h
>
> diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
> index 562ea68..fc073b5 100644
> --- a/drivers/net/fs_enet/Kconfig
> +++ b/drivers/net/fs_enet/Kconfig
> @@ -1,9 +1,13 @@
> config FS_ENET
> tristate "Freescale Ethernet Driver"
> - depends on CPM1 || CPM2
> + depends on CPM1 || CPM2 || PPC_MPC512x
> select MII
> select PHYLIB
>
> +config FS_ENET_MPC5121_FEC
> + def_bool y if (FS_ENET && PPC_MPC512x)
> + select FS_ENET_HAS_FEC
> +
> config FS_ENET_HAS_SCC
> bool "Chip has an SCC usable for ethernet"
> depends on FS_ENET && (CPM1 || CPM2)
> @@ -16,13 +20,13 @@ config FS_ENET_HAS_FCC
>
> config FS_ENET_HAS_FEC
> bool "Chip has an FEC usable for ethernet"
> - depends on FS_ENET && CPM1
> + depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC)
> select FS_ENET_MDIO_FEC
> default y
>
> config FS_ENET_MDIO_FEC
> tristate "MDIO driver for FEC"
> - depends on FS_ENET && CPM1
> + depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC)
>
> config FS_ENET_MDIO_FCC
> tristate "MDIO driver for FCC"
> diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
> index c34a7e0..6bce5c8 100644
> --- a/drivers/net/fs_enet/fs_enet-main.c
> +++ b/drivers/net/fs_enet/fs_enet-main.c
> @@ -1095,6 +1095,10 @@ static struct of_device_id fs_enet_match[] = {
> #endif
> #ifdef CONFIG_FS_ENET_HAS_FEC
> {
> + .compatible = "fsl,mpc5121-fec",
> + .data = (void *)&fs_fec_ops,
> + },
> + {
> .compatible = "fsl,pq1-fec-enet",
> .data = (void *)&fs_fec_ops,
> },
> diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
> index ef01e09..df935e8 100644
> --- a/drivers/net/fs_enet/fs_enet.h
> +++ b/drivers/net/fs_enet/fs_enet.h
> @@ -13,11 +13,47 @@
>
> #ifdef CONFIG_CPM1
> #include <asm/cpm1.h>
> +#endif
> +
> +#if defined(CONFIG_FS_ENET_HAS_FEC)
> +#include <asm/cpm.h>
> +#include "mpc8xx_fec.h"
> +#include "mpc5121_fec.h"
Do we really need the new header files? Why not adding the struct
definitions here or use "struct fec" from 8xx_immap.h. See below.
> struct fec_info {
> - fec_t __iomem *fecp;
> + void __iomem *fecp;
A name like fec_base or base_addr would help to avoid confusion with a
pointer to the old fec struct.
> + u32 __iomem *fec_r_cntrl;
> + u32 __iomem *fec_ecntrl;
> + u32 __iomem *fec_ievent;
> + u32 __iomem *fec_mii_data;
> + u32 __iomem *fec_mii_speed;
> u32 mii_speed;
> };
> +
> +struct reg_tbl {
A more specific name would be nice, e.g. "fec_reg_tbl" or "fec_regs".
> + u32 __iomem *fec_ievent;
> + u32 __iomem *fec_imask;
> + u32 __iomem *fec_r_des_active;
> + u32 __iomem *fec_x_des_active;
> + u32 __iomem *fec_r_des_start;
> + u32 __iomem *fec_x_des_start;
> + u32 __iomem *fec_r_cntrl;
> + u32 __iomem *fec_ecntrl;
> + u32 __iomem *fec_ivec;
> + u32 __iomem *fec_mii_speed;
> + u32 __iomem *fec_addr_low;
> + u32 __iomem *fec_addr_high;
> + u32 __iomem *fec_hash_table_high;
> + u32 __iomem *fec_hash_table_low;
> + u32 __iomem *fec_r_buff_size;
> + u32 __iomem *fec_r_bound;
> + u32 __iomem *fec_r_fstart;
> + u32 __iomem *fec_x_fstart;
> + u32 __iomem *fec_fun_code;
> + u32 __iomem *fec_r_hash;
> + u32 __iomem *fec_x_cntrl;
> + u32 __iomem *fec_dma_control;
> +};
> #endif
>
> #ifdef CONFIG_CPM2
> @@ -113,7 +149,9 @@ struct fs_enet_private {
> struct {
> int idx; /* FEC1 = 0, FEC2 = 1 */
> void __iomem *fecp; /* hw registers */
See above.
> + struct reg_tbl *rtbl; /* used registers table */
> u32 hthi, htlo; /* state for multicast */
> + u32 fec_id;
> } fec;
>
> struct {
> diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
> index a664aa1..fe9e368 100644
> --- a/drivers/net/fs_enet/mac-fec.c
> +++ b/drivers/net/fs_enet/mac-fec.c
> @@ -64,29 +64,40 @@
> #endif
>
> /* write */
> -#define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fec_ ## _reg, (_v))
> +#define FW(_regp, _reg, _v) __fs_out32((_regp)->fec_ ## _reg, (_v))
>
> /* read */
> -#define FR(_fecp, _reg) __fs_in32(&(_fecp)->fec_ ## _reg)
> +#define FR(_regp, _reg) __fs_in32((_regp)->fec_ ## _reg)
>
> /* set bits */
> -#define FS(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) | (_v))
> +#define FS(_regp, _reg, _v) FW(_regp, _reg, FR(_regp, _reg) | (_v))
>
> /* clear bits */
> -#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
> +#define FC(_regp, _reg, _v) FW(_regp, _reg, FR(_regp, _reg) & ~(_v))
> +
> +/* register address macros */
> +#define fec_reg_addr(_type, _reg) \
> + (fep->fec.rtbl->fec_##_reg = (u32 __iomem *)((u32)fep->fec.fecp + \
> + (u32)&((__typeof__(_type) *)NULL)->fec_##_reg))
I think you don't need the cast in the first line and using "offsetof"
would simplify the macro further. I would also use _fep as first
argument to make this macro function more transparent.
> +#define fec_reg_mpc8xx(_reg) \
> + fec_reg_addr(struct mpc8xx_fec, _reg)
> +
> +#define fec_reg_mpc5121(_reg) \
> + fec_reg_addr(struct mpc5121_fec, _reg)
Also, s/fec_reg_addr/fec_set_reg_addr/ would give the three macros above
a more appropriate name.
> /*
> * Delay to wait for FEC reset command to complete (in us)
> */
> #define FEC_RESET_DELAY 50
>
> -static int whack_reset(fec_t __iomem *fecp)
> +static int whack_reset(struct reg_tbl *regp)
> {
> int i;
>
> - FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
> + FW(regp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
> for (i = 0; i < FEC_RESET_DELAY; i++) {
> - if ((FR(fecp, ecntrl) & FEC_ECNTRL_RESET) == 0)
> + if ((FR(regp, ecntrl) & FEC_ECNTRL_RESET) == 0)
> return 0; /* OK */
> udelay(1);
> }
> @@ -106,6 +117,50 @@ static int do_pd_setup(struct fs_enet_private *fep)
> if (!fep->fcc.fccp)
> return -EINVAL;
>
> + fep->fec.rtbl = kzalloc(sizeof(*fep->fec.rtbl), GFP_KERNEL);
> + if (!fep->fec.rtbl) {
> + iounmap(fep->fec.fecp);
> + return -ENOMEM;
> + }
Any reason why not adding the struct directly to fep->fec? It would save
some code for alloc/free and the addresses would be "closer" (cache wise).
> + if (of_device_is_compatible(ofdev->node, "fsl,mpc5121-fec")) {
> + fep->fec.fec_id = FS_ENET_MPC5121_FEC;
> + fec_reg_mpc5121(ievent);
> + fec_reg_mpc5121(imask);
> + fec_reg_mpc5121(r_cntrl);
> + fec_reg_mpc5121(ecntrl);
> + fec_reg_mpc5121(r_des_active);
> + fec_reg_mpc5121(x_des_active);
> + fec_reg_mpc5121(r_des_start);
> + fec_reg_mpc5121(x_des_start);
> + fec_reg_mpc5121(addr_low);
> + fec_reg_mpc5121(addr_high);
> + fec_reg_mpc5121(hash_table_high);
> + fec_reg_mpc5121(hash_table_low);
> + fec_reg_mpc5121(r_buff_size);
> + fec_reg_mpc5121(mii_speed);
> + fec_reg_mpc5121(x_cntrl);
> + fec_reg_mpc5121(dma_control);
> + } else {
> + fec_reg_mpc8xx(ievent);
> + fec_reg_mpc8xx(imask);
> + fec_reg_mpc8xx(r_cntrl);
> + fec_reg_mpc8xx(ecntrl);
> + fec_reg_mpc8xx(mii_speed);
> + fec_reg_mpc8xx(r_des_active);
> + fec_reg_mpc8xx(x_des_active);
> + fec_reg_mpc8xx(r_des_start);
> + fec_reg_mpc8xx(x_des_start);
> + fec_reg_mpc8xx(ivec);
> + fec_reg_mpc8xx(addr_low);
> + fec_reg_mpc8xx(addr_high);
> + fec_reg_mpc8xx(hash_table_high);
> + fec_reg_mpc8xx(hash_table_low);
> + fec_reg_mpc8xx(r_buff_size);
> + fec_reg_mpc8xx(x_fstart);
> + fec_reg_mpc8xx(r_hash);
> + fec_reg_mpc8xx(x_cntrl);
> + }
> return 0;
> }
>
> @@ -162,15 +217,17 @@ static void free_bd(struct net_device *dev)
>
> static void cleanup_data(struct net_device *dev)
> {
> - /* nothing */
> + struct fs_enet_private *fep = netdev_priv(dev);
> +
> + kfree(fep->fec.rtbl);
> }
See above.
[snip]
> +++ b/drivers/net/fs_enet/mpc5121_fec.h
> @@ -0,0 +1,64 @@
> +/*
> + * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
> + *
> + * Author: John Rigby, <jrigby@freescale.com>
> + *
> + * Modified version of drivers/net/fec.h:
> + *
> + * fec.h -- Fast Ethernet Controller for Motorola ColdFire SoC
> + * processors.
> + *
> + * (C) Copyright 2000-2005, Greg Ungerer (gerg@snapgear.com)
> + * (C) Copyright 2000-2001, Lineo (www.lineo.com)
> + *
> + * This 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.
> + */
> +#ifndef MPC5121_FEC_H
> +#define MPC5121_FEC_H
> +
> +struct mpc5121_fec {
> + u32 fec_reserved0;
> + u32 fec_ievent; /* Interrupt event reg */
> + u32 fec_imask; /* Interrupt mask reg */
> + u32 fec_reserved1;
> + u32 fec_r_des_active; /* Receive descriptor reg */
> + u32 fec_x_des_active; /* Transmit descriptor reg */
> + u32 fec_reserved2[3];
> + u32 fec_ecntrl; /* Ethernet control reg */
> + u32 fec_reserved3[6];
> + u32 fec_mii_data; /* MII manage frame reg */
> + u32 fec_mii_speed; /* MII speed control reg */
> + u32 fec_reserved4[7];
> + u32 fec_mib_ctrlstat; /* MIB control/status reg */
> + u32 fec_reserved5[7];
> + u32 fec_r_cntrl; /* Receive control reg */
> + u32 fec_reserved6[15];
> + u32 fec_x_cntrl; /* Transmit Control reg */
> + u32 fec_reserved7[7];
> + u32 fec_addr_low; /* Low 32bits MAC address */
> + u32 fec_addr_high; /* High 16bits MAC address */
> + u32 fec_opd; /* Opcode + Pause duration */
> + u32 fec_reserved8[10];
> + u32 fec_hash_table_high; /* High 32bits hash table */
> + u32 fec_hash_table_low; /* Low 32bits hash table */
> + u32 fec_grp_hash_table_high; /* High 32bits hash table */
> + u32 fec_grp_hash_table_low; /* Low 32bits hash table */
> + u32 fec_reserved9[7];
> + u32 fec_x_wmrk; /* FIFO transmit water mark */
> + u32 fec_reserved10;
> + u32 fec_r_bound; /* FIFO receive bound reg */
> + u32 fec_r_fstart; /* FIFO receive start reg */
> + u32 fec_reserved11[11];
> + u32 fec_r_des_start; /* Receive descriptor ring */
> + u32 fec_x_des_start; /* Transmit descriptor ring */
> + u32 fec_r_buff_size; /* Maximum receive buff size */
> + u32 fec_reserved12[26];
> + u32 fec_dma_control; /* DMA Endian and other ctrl */
> +};
> +
> +#define FS_ENET_MPC5121_FEC 0x1
> +
> +#endif /* MPC5121_FEC_H */
> diff --git a/drivers/net/fs_enet/mpc8xx_fec.h b/drivers/net/fs_enet/mpc8xx_fec.h
> new file mode 100644
> index 0000000..aa78445
> --- /dev/null
> +++ b/drivers/net/fs_enet/mpc8xx_fec.h
> @@ -0,0 +1,37 @@
> +/* MPC860T Fast Ethernet Controller. It isn't part of the CPM, but
> + * it fits within the address space.
> + */
> +
The usual "#ifndef" stuff is missing, in case you keep it.
> +struct mpc8xx_fec {
> + uint fec_addr_low; /* lower 32 bits of station address */
> + ushort fec_addr_high; /* upper 16 bits of station address */
> + ushort res1; /* reserved */
> + uint fec_hash_table_high; /* upper 32-bits of hash table */
> + uint fec_hash_table_low; /* lower 32-bits of hash table */
> + uint fec_r_des_start; /* beginning of Rx descriptor ring */
> + uint fec_x_des_start; /* beginning of Tx descriptor ring */
> + uint fec_r_buff_size; /* Rx buffer size */
> + uint res2[9]; /* reserved */
> + uint fec_ecntrl; /* ethernet control register */
> + uint fec_ievent; /* interrupt event register */
> + uint fec_imask; /* interrupt mask register */
> + uint fec_ivec; /* interrupt level and vector status */
> + uint fec_r_des_active; /* Rx ring updated flag */
> + uint fec_x_des_active; /* Tx ring updated flag */
> + uint res3[10]; /* reserved */
> + uint fec_mii_data; /* MII data register */
> + uint fec_mii_speed; /* MII speed control register */
> + uint res4[17]; /* reserved */
> + uint fec_r_bound; /* end of RAM (read-only) */
> + uint fec_r_fstart; /* Rx FIFO start address */
> + uint res5[6]; /* reserved */
> + uint fec_x_fstart; /* Tx FIFO start address */
> + uint res6[17]; /* reserved */
> + uint fec_fun_code; /* fec SDMA function code */
> + uint res7[3]; /* reserved */
> + uint fec_r_cntrl; /* Rx control register */
> + uint fec_r_hash; /* Rx hash register */
> + uint res8[14]; /* reserved */
> + uint fec_x_cntrl; /* Tx control register */
> + uint res9[0x1e]; /* reserved */
> +};
As mentioned above, I do not see a need for two extra header files. The
struct(s) could be added to fec.h. Also a similar "struct fec" is
already defined in "arch/powerpc/include/asm/8xx_immap.h", which could
be used instead of "struct mpc8xx_fec" above.
Wolfgang.
^ permalink raw reply
* Re: [PATCH 11/11] powerpc/mpc5121: Add default config for MPC5121ADS
From: Grant Likely @ 2010-01-21 17:47 UTC (permalink / raw)
To: Anatolij Gustschin; +Cc: linuxppc-dev, wd, dzu
In-Reply-To: <1263932653-3634-12-git-send-email-agust@denx.de>
On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust@denx.de> wrote:
> From: Wolfgang Denk <wd@denx.de>
>
> As more MPC512x based boards will be coming soon, a new directory
> arch/powerpc/configs/512x/ for board specific config files is created,
> following the example of other processor families.
>
> In a first step, we just copy (and update) the existing defconfig
> file for the mpc5121ads board. When new boards get added, the old
> arch/powerpc/configs/mpc5121_defconfig file will get adjusted to
> allow for a generic kernel image for MPC512x based boards.
>
> Signed-off-by: Wolfgang Denk <wd@denx.de>
> Signed-off-by: Detlev Zundel <dzu@denx.de>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> ---
> This default config is provided only for easier testing.
>
> =A0arch/powerpc/configs/512x/mpc5121ads_defconfig | 1662 ++++++++++++++++=
++++++++
I'm not a fan off adding one-per-board defconfigs to mainline. To
start, please just name this arch/powerpc/configs/512x_defconfig
g.
^ permalink raw reply
* Re: [PATCH 08/11] powerpc/mpc5121: add USB host support
From: Grant Likely @ 2010-01-21 17:43 UTC (permalink / raw)
To: Anatolij Gustschin
Cc: wd, dzu, devicetree-discuss, linux-usb, linuxppc-dev,
Bruce Schmid
In-Reply-To: <1263932653-3634-9-git-send-email-agust@denx.de>
On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust@denx.de> wrote:
> Platform specific code for MPC5121 USB Host support.
> MPC5121 Rev 2.0 silicon EHCI registers are big endian.
> Add appropriate support by specifying "big-endian-regs"
> property in device tree node for USB controller. Also
> allow specifying DRVVBUS and PWR_FAULT signal polarity
> of MPC5121 internal PHY using "invert-drvvbus" and
> "invert-pwr-fault" properties.
>
> Signed-off-by: Bruce Schmid <duck@freescale.com>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: linux-usb@vger.kernel.org
> Cc: Grant Likely <grant.likely@secretlab.ca>
> ---
> Note that EHCI FSL driver extention in this patch
> applies on top of the following two patches (in the
> linux-next tree):
>
> commit 23c3314b88f91db51bd198ed92e34cffb67788dd
> Author: Anton Vorontsov <avorontsov@ru.mvista.com>
> Date: =A0 Mon Dec 14 18:41:12 2009 +0300
>
> =A0 =A0USB: ehci-fsl: Add power management support
>
> commit bf4bf2d9f646eb0cc531d213a13ffcedf9d6785f
> Author: Anton Vorontsov <avorontsov@ru.mvista.com>
> Date: =A0 Mon Dec 14 18:41:05 2009 +0300
>
> =A0 =A0USB: ehci-fsl: Fix sparse warnings
>
> =A0Documentation/powerpc/dts-bindings/fsl/usb.txt | =A0 =A08 ++
> =A0arch/powerpc/platforms/512x/Kconfig =A0 =A0 =A0 =A0 =A0 =A0| =A0 =A06 =
+
> =A0arch/powerpc/platforms/512x/Makefile =A0 =A0 =A0 =A0 =A0 | =A0 =A02 +-
> =A0arch/powerpc/platforms/512x/mpc5121_ads.c =A0 =A0 =A0| =A0 =A01 +
> =A0arch/powerpc/platforms/512x/mpc5121_usb.c =A0 =A0 =A0| =A0117 ++++++++=
++++++++++++++++
> =A0arch/powerpc/platforms/512x/mpc512x.h =A0 =A0 =A0 =A0 =A0| =A0 =A01 +
> =A0arch/powerpc/sysdev/fsl_soc.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0=
10 ++
> =A0arch/powerpc/sysdev/fsl_soc.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0=
=A09 ++
> =A0drivers/usb/host/ehci-fsl.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0116 +++++++++++++++++-------
> =A0drivers/usb/host/ehci-fsl.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0 19 ++++-
> =A0drivers/usb/host/ehci-mem.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0 =A02 +-
> =A0include/linux/fsl_devices.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0 10 ++
> =A012 files changed, 265 insertions(+), 36 deletions(-)
> =A0create mode 100644 arch/powerpc/platforms/512x/mpc5121_usb.c
>
> diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentati=
on/powerpc/dts-bindings/fsl/usb.txt
> index b001524..9050154 100644
> --- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
> +++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
> @@ -33,6 +33,14 @@ Recommended properties :
> =A0- interrupt-parent : the phandle for the interrupt controller that
> =A0 =A0services interrupts for this device.
>
> +Optional properties :
> + - big-endian-regs : boolean; if defined, indicates the USB host
> + =A0 controller registers format is big endian.
Rather than testing for this explicitly, add fsl,mpc5121-usb2-dr to
the match table and use the .data pointer for setting device specific
quirks.
> + - invert-drvvbus : boolean; for MPC5121 only. Indicates the port
> + =A0 power polarity of internal PHY signal DRVVBUS is inverted.
> + - invert-pwr-fault : boolean; for MPC5121 only. Indicates the
> + =A0 PWR_FAULT signal polarity is inverted.
These are also characteristics of the chip, not the board, right? If
so then these also can be determined implicitly by the compatible
value.
Finally, these are all freescale specific properties. If you still
need them, then prefix the property names with 'fsl,'
> +
> =A0Example multi port host USB controller device node :
> =A0 =A0 =A0 =A0usb@22000 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0compatible =3D "fsl-usb2-mph";
> diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms=
/512x/Kconfig
> index 4dac9b0..3fec738 100644
> --- a/arch/powerpc/platforms/512x/Kconfig
> +++ b/arch/powerpc/platforms/512x/Kconfig
> @@ -9,6 +9,9 @@ config PPC_MPC512x
> =A0config PPC_MPC5121
> =A0 =A0 =A0 =A0bool
> =A0 =A0 =A0 =A0select PPC_MPC512x
> + =A0 =A0 =A0 select USB_ARCH_HAS_EHCI
> + =A0 =A0 =A0 select USB_EHCI_BIG_ENDIAN_DESC
> + =A0 =A0 =A0 select USB_EHCI_BIG_ENDIAN_MMIO
>
> =A0config MPC5121_ADS
> =A0 =A0 =A0 =A0bool "Freescale MPC5121E ADS"
> @@ -30,3 +33,6 @@ config MPC5121_GENERIC
>
> =A0 =A0 =A0 =A0 =A0Compatible boards include: =A0Protonic LVT base boards=
(ZANMCU
> =A0 =A0 =A0 =A0 =A0and VICVT2).
> +
> +config USB_FSL_BIG_ENDIAN_MMIO
> + =A0 =A0 =A0 bool
What's this for?
> diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platform=
s/512x/Makefile
> index 90be2f5..49adabc 100644
> --- a/arch/powerpc/platforms/512x/Makefile
> +++ b/arch/powerpc/platforms/512x/Makefile
> @@ -1,6 +1,6 @@
> =A0#
> =A0# Makefile for the Freescale PowerPC 512x linux kernel.
> =A0#
> -obj-y =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0+=3D clock.o mp=
c512x_shared.o
> +obj-y =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0+=3D clock.o mp=
c512x_shared.o mpc5121_usb.o
> =A0obj-$(CONFIG_MPC5121_ADS) =A0 =A0 =A0+=3D mpc5121_ads.o mpc5121_ads_cp=
ld.o
> =A0obj-$(CONFIG_MPC5121_GENERIC) =A0+=3D mpc5121_generic.o
> diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/pla=
tforms/512x/mpc5121_ads.c
> index 2f40404..a497c14 100644
> --- a/arch/powerpc/platforms/512x/mpc5121_ads.c
> +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
> @@ -42,6 +42,7 @@ static void __init mpc5121_ads_setup_arch(void)
> =A0 =A0 =A0 =A0for_each_compatible_node(np, "pci", "fsl,mpc5121-pci")
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mpc83xx_add_bridge(np);
> =A0#endif
> + =A0 =A0 =A0 mpc5121_usb_init();
> =A0}
>
> =A0static void __init mpc5121_ads_init_IRQ(void)
> diff --git a/arch/powerpc/platforms/512x/mpc5121_usb.c b/arch/powerpc/pla=
tforms/512x/mpc5121_usb.c
> new file mode 100644
> index 0000000..7b45651
> --- /dev/null
> +++ b/arch/powerpc/platforms/512x/mpc5121_usb.c
> @@ -0,0 +1,117 @@
> +/*
> + * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights rese=
rved.
> + *
> + * Author: Bruce Schmid <duck@freescale.com>, Tue Oct 2 2007
> + *
> + * Description:
> + * MPC5121 USB platform-specific routines
> + *
> + * This 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/clk.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/fsl_devices.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/stddef.h>
> +#include <linux/of_platform.h>
> +#include <sysdev/fsl_soc.h>
> +
> +#define USBGENCTRL =A0 =A0 =A0 =A0 =A0 =A0 0x200 =A0 =A0 =A0 =A0 =A0 /* =
NOTE: big endian */
> +#define GC_WU_INT_CLR =A0 =A0 =A0 =A0 =A0(1 << 5) =A0 =A0 =A0 =A0/* Wake=
up int clear */
> +#define GC_ULPI_SEL =A0 =A0 =A0 =A0 =A0 =A0(1 << 4) =A0 =A0 =A0 =A0/* UL=
PI i/f select (usb0 only)*/
> +#define GC_PPP =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 3) =A0 =A0 =A0 =A0/=
* Inv. Port Power Polarity */
> +#define GC_PFP =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 2) =A0 =A0 =A0 =A0/=
* Inv. Power Fault Polarity */
> +#define GC_WU_ULPI_EN =A0 =A0 =A0 =A0 =A0(1 << 1) =A0 =A0 =A0 =A0/* Wake=
up on ULPI event */
> +#define GC_WU_IE =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 1) =A0 =A0 =A0 =A0/* =
Wakeup interrupt enable */
> +
> +#define ISIPHYCTRL =A0 =A0 =A0 =A0 =A0 =A0 0x204 =A0 =A0 =A0 =A0 =A0 /* =
NOTE: big endian */
> +#define PHYCTRL_PHYE =A0 =A0 =A0 =A0 =A0 (1 << 4) =A0 =A0 =A0 =A0/* On-c=
hip UTMI PHY enable */
> +#define PHYCTRL_BSENH =A0 =A0 =A0 =A0 =A0(1 << 3) =A0 =A0 =A0 =A0/* Bit =
Stuff Enable High */
> +#define PHYCTRL_BSEN =A0 =A0 =A0 =A0 =A0 (1 << 2) =A0 =A0 =A0 =A0/* Bit =
Stuff Enable */
> +#define PHYCTRL_LSFE =A0 =A0 =A0 =A0 =A0 (1 << 1) =A0 =A0 =A0 =A0/* Line=
State Filter Enable */
> +#define PHYCTRL_PXE =A0 =A0 =A0 =A0 =A0 =A0(1 << 0) =A0 =A0 =A0 =A0/* PH=
Y oscillator enable */
> +
> +static struct clk *dr_clk1;
> +static struct clk *dr_clk2;
> +static int dr_used;
> +
> +static int mpc5121_usb_dr_init(struct platform_device *pdev)
> +{
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata =3D pdev->dev.platform=
_data;
> +
> + =A0 =A0 =A0 /* enable the clock if we haven't already */
> + =A0 =A0 =A0 if (!dr_used) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dr_clk1 =3D clk_get(&pdev->dev, "usb1_clk")=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (IS_ERR(dr_clk1)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&pdev->dev, "usb1: =
clk_get failed\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_enable(dr_clk1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dr_clk2 =3D clk_get(&pdev->dev, "usb2_clk")=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (IS_ERR(dr_clk2)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&pdev->dev, "usb2: =
clk_get failed\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_enable(dr_clk2);
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 dr_used++;
> +
> + =A0 =A0 =A0 pdata->big_endian_desc =3D 1;
> + =A0 =A0 =A0 pdata->es =3D 1;
> +
> + =A0 =A0 =A0 if (pdata->phy_mode =3D=3D FSL_USB2_PHY_UTMI_WIDE) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct device_node *np;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 u32 reg =3D 0;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 np =3D of_find_compatible_node(NULL, NULL, =
"fsl,mpc5121-usb2-dr");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("No USB node found\n=
");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "invert-drvvbus", N=
ULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg |=3D GC_PPP;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "invert-pwr-fault",=
NULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg |=3D GC_PFP;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put(np);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_=
PHYE | PHYCTRL_PXE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(pdata->regs + USBGENCTRL, reg);
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static void mpc5121_usb_dr_uninit(struct platform_device *pdev)
> +{
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata =3D pdev->dev.platform=
_data;
> +
> + =A0 =A0 =A0 pdata->regs =3D NULL;
> +
> + =A0 =A0 =A0 dr_used--;
> + =A0 =A0 =A0 if (!dr_used) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_disable(dr_clk1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_disable(dr_clk2);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_put(dr_clk1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_put(dr_clk2);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dr_clk1 =3D NULL;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dr_clk2 =3D NULL;
> + =A0 =A0 =A0 }
> +}
> +
> +void mpc5121_usb_init(void)
> +{
> + =A0 =A0 =A0 fsl_platform_usb_ops.init =3D mpc5121_usb_dr_init;
> + =A0 =A0 =A0 fsl_platform_usb_ops.uninit =3D mpc5121_usb_dr_uninit;
> +}
Hmmm... I'm not fond of using the fsl_soc.c stuff instead of
drivers/usb/host/ehci-ppc-of.c, but I understand why you're doing it.
Given the constraints, I guess this is okay, but this USB common code
needs some refactoring (I'm not asking you to do it).
> diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platfor=
ms/512x/mpc512x.h
> index c38875c..e92a282 100644
> --- a/arch/powerpc/platforms/512x/mpc512x.h
> +++ b/arch/powerpc/platforms/512x/mpc512x.h
> @@ -13,5 +13,6 @@
> =A0#define __MPC512X_H__
> =A0extern void __init mpc512x_init_IRQ(void);
> =A0extern void mpc512x_restart(char *cmd);
> +extern void mpc5121_usb_init(void);
> =A0void __init mpc512x_declare_of_platform_devices(void);
> =A0#endif =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* __MPC512X_H_=
_ */
> diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.=
c
> index b91f7ac..19a455d 100644
> --- a/arch/powerpc/sysdev/fsl_soc.c
> +++ b/arch/powerpc/sysdev/fsl_soc.c
> @@ -209,6 +209,9 @@ static int __init of_add_fixed_phys(void)
> =A0arch_initcall(of_add_fixed_phys);
> =A0#endif /* CONFIG_FIXED_PHY */
>
> +struct fsl_platform_usb_ops fsl_platform_usb_ops;
> +EXPORT_SYMBOL(fsl_platform_usb_ops);
> +
> =A0static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
> =A0{
> =A0 =A0 =A0 =A0if (!phy_type)
> @@ -267,6 +270,9 @@ static int __init fsl_usb_of_init(void)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (prop)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0usb_data.port_enables |=3D=
FSL_USB2_PORT1_ENABLED;
>
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "big-endian-regs", =
NULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 usb_data.big_endian_mmio =
=3D 1;
> +
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0prop =3D of_get_property(np, "phy_type", N=
ULL);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0usb_data.phy_mode =3D determine_usb_phy(pr=
op);
>
> @@ -332,9 +338,13 @@ static int __init fsl_usb_of_init(void)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ret =3D -EINVAL;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto err;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "big-endian-regs", =
NULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 usb_data.big_endian_mmio =
=3D 1;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0prop =3D of_get_property(np, "phy_type", N=
ULL);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0usb_data.phy_mode =3D determine_usb_phy(pr=
op);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 usb_data.platform_init =3D fsl_platform_usb=
_ops.init;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 usb_data.platform_uninit =3D fsl_platform_u=
sb_ops.uninit;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (usb_dev_dr_host) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0usb_dev_dr_host->dev.coher=
ent_dma_mask =3D 0xffffffffUL;
> diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.=
h
> index 42381bb..19754be 100644
> --- a/arch/powerpc/sysdev/fsl_soc.h
> +++ b/arch/powerpc/sysdev/fsl_soc.h
> @@ -35,5 +35,14 @@ struct platform_diu_data_ops {
> =A0extern struct platform_diu_data_ops diu_ops;
> =A0#endif
>
> +struct platform_device;
> +
> +struct fsl_platform_usb_ops {
> + =A0 =A0 =A0 int (*init)(struct platform_device *);
> + =A0 =A0 =A0 void (*uninit)(struct platform_device *);
> +};
> +
> +extern struct fsl_platform_usb_ops fsl_platform_usb_ops;
> +
> =A0#endif
> =A0#endif
> diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
> index 0e26aa1..c4ec00c 100644
> --- a/drivers/usb/host/ehci-fsl.c
> +++ b/drivers/usb/host/ehci-fsl.c
> @@ -57,7 +57,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *dr=
iver,
> =A0 =A0 =A0 =A0pr_debug("initializing FSL-SOC USB Controller\n");
>
> =A0 =A0 =A0 =A0/* Need platform data for setup */
> - =A0 =A0 =A0 pdata =3D (struct fsl_usb2_platform_data *)pdev->dev.platfo=
rm_data;
> + =A0 =A0 =A0 pdata =3D pdev->dev.platform_data;
> =A0 =A0 =A0 =A0if (!pdata) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev_err(&pdev->dev,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"No platform data for %s.\=
n", dev_name(&pdev->dev));
> @@ -77,14 +77,13 @@ static int usb_hcd_fsl_probe(const struct hc_driver *=
driver,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return -ENODEV;
> =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 res =3D platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> - =A0 =A0 =A0 if (!res) {
> + =A0 =A0 =A0 irq =3D platform_get_irq(pdev, 0);
> + =A0 =A0 =A0 if (irq < 0) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev_err(&pdev->dev,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"Found HC with no IRQ. Che=
ck %s setup!\n",
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev_name(&pdev->dev));
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return -ENODEV;
> =A0 =A0 =A0 =A0}
> - =A0 =A0 =A0 irq =3D res->start;
Put this hunk in a separate patch.
>
> =A0 =A0 =A0 =A0hcd =3D usb_create_hcd(driver, &pdev->dev, dev_name(&pdev-=
>dev));
> =A0 =A0 =A0 =A0if (!hcd) {
> @@ -116,13 +115,39 @@ static int usb_hcd_fsl_probe(const struct hc_driver=
*driver,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto err3;
> =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 /* Enable USB controller */
> - =A0 =A0 =A0 temp =3D in_be32(hcd->regs + 0x500);
> - =A0 =A0 =A0 out_be32(hcd->regs + 0x500, temp | 0x4);
> + =A0 =A0 =A0 pdata->regs =3D hcd->regs;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* do platform specific init: check the clock, grab/confi=
g pins, etc.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (pdata->platform_init && pdata->platform_init(pdev)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval =3D -ENODEV;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto err3;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Check if it is MPC5121 SoC, otherwise set pdata->have_=
sysif_regs
> + =A0 =A0 =A0 =A0* flag for 83xx or 8536 system interface registers.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (pdata->big_endian_mmio)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temp =3D in_be32(hcd->regs + FSL_SOC_USB_ID=
);
> + =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temp =3D in_le32(hcd->regs + FSL_SOC_USB_ID=
);
> +
> + =A0 =A0 =A0 if ((temp & ID_MSK) !=3D (~((temp & NID_MSK) >> 8) & ID_MSK=
))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->have_sysif_regs =3D 1;
> +
> + =A0 =A0 =A0 /* Enable USB controller, 83xx or 8536 */
> + =A0 =A0 =A0 if (pdata->have_sysif_regs)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4=
);
>
> =A0 =A0 =A0 =A0/* Set to Host mode */
> - =A0 =A0 =A0 temp =3D in_le32(hcd->regs + 0x1a8);
> - =A0 =A0 =A0 out_le32(hcd->regs + 0x1a8, temp | 0x3);
> + =A0 =A0 =A0 if (pdata->big_endian_mmio) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 setbits32(hcd->regs + FSL_SOC_USB_USBMODE, =
USBMODE_CM_HOST);
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clrsetbits_le32(hcd->regs + FSL_SOC_USB_USB=
MODE,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 USBMODE_CM_=
MASK, USBMODE_CM_HOST);
> + =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0retval =3D usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHAR=
ED);
> =A0 =A0 =A0 =A0if (retval !=3D 0)
> @@ -137,6 +162,8 @@ static int usb_hcd_fsl_probe(const struct hc_driver *=
driver,
> =A0 =A0 =A0 =A0usb_put_hcd(hcd);
> =A0 =A0 =A0 err1:
> =A0 =A0 =A0 =A0dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->=
dev), retval);
> + =A0 =A0 =A0 if (pdata->platform_uninit)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->platform_uninit(pdev);
> =A0 =A0 =A0 =A0return retval;
> =A0}
>
> @@ -154,17 +181,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver=
*driver,
> =A0static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct platfo=
rm_device *pdev)
> =A0{
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata =3D pdev->dev.platform=
_data;
> +
> =A0 =A0 =A0 =A0usb_remove_hcd(hcd);
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* do platform specific un-initialization:
> + =A0 =A0 =A0 =A0* release iomux pins, disable clock, etc.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (pdata->platform_uninit)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->platform_uninit(pdev);
> =A0 =A0 =A0 =A0iounmap(hcd->regs);
> =A0 =A0 =A0 =A0release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> =A0 =A0 =A0 =A0usb_put_hcd(hcd);
> =A0}
>
> -static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 enum fsl_usb2_p=
hy_modes phy_mode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unsigned int po=
rt_offset)
> +static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0enum fsl_usb=
2_phy_modes phy_mode,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned int=
port_offset)
> =A0{
> - =A0 =A0 =A0 u32 portsc =3D 0;
> + =A0 =A0 =A0 u32 portsc;
> +
> + =A0 =A0 =A0 portsc =3D ehci_readl(ehci, &ehci->regs->port_status[port_o=
ffset]);
> + =A0 =A0 =A0 portsc &=3D ~(PORT_PTS_MSK | PORT_PTS_PTW);
> +
> =A0 =A0 =A0 =A0switch (phy_mode) {
> =A0 =A0 =A0 =A0case FSL_USB2_PHY_ULPI:
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0portsc |=3D PORT_PTS_ULPI;
> @@ -184,20 +224,21 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci=
,
> =A0 =A0 =A0 =A0ehci_writel(ehci, portsc, &ehci->regs->port_status[port_of=
fset]);
> =A0}
>
> -static void mpc83xx_usb_setup(struct usb_hcd *hcd)
> +static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
> =A0{
> - =A0 =A0 =A0 struct ehci_hcd *ehci =3D hcd_to_ehci(hcd);
> + =A0 =A0 =A0 struct usb_hcd *hcd =3D ehci_to_hcd(ehci);
> =A0 =A0 =A0 =A0struct fsl_usb2_platform_data *pdata;
> =A0 =A0 =A0 =A0void __iomem *non_ehci =3D hcd->regs;
> - =A0 =A0 =A0 u32 temp;
> + =A0 =A0 =A0 u32 tmp;
> +
> + =A0 =A0 =A0 pdata =3D hcd->self.controller->platform_data;
>
> - =A0 =A0 =A0 pdata =3D
> - =A0 =A0 =A0 =A0 =A0 (struct fsl_usb2_platform_data *)hcd->self.controll=
er->
> - =A0 =A0 =A0 =A0 =A0 platform_data;
> =A0 =A0 =A0 =A0/* Enable PHY interface in the control reg. */
> - =A0 =A0 =A0 temp =3D in_be32(non_ehci + FSL_SOC_USB_CTRL);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
> + =A0 =A0 =A0 if (pdata->have_sysif_regs) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 tmp =3D in_be32(non_ehci + FSL_SOC_USB_CTRL=
);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_CTRL, tmp |=
0x00000004);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0=
000001b);
> + =A0 =A0 =A0 }
>
> =A0#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
> =A0 =A0 =A0 =A0/*
> @@ -214,7 +255,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
>
> =A0 =A0 =A0 =A0if ((pdata->operating_mode =3D=3D FSL_USB2_DR_HOST) ||
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(pdata->operating_mode =3D=
=3D FSL_USB2_DR_OTG))
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mpc83xx_setup_phy(ehci, pdata->phy_mode, 0)=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0=
);
>
> =A0 =A0 =A0 =A0if (pdata->operating_mode =3D=3D FSL_USB2_MPH_HOST) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned int chip, rev, svr;
> @@ -228,27 +269,31 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ehci->has_fsl_port_bug =3D=
1;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (pdata->port_enables & FSL_USB2_PORT0_E=
NABLED)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 mpc83xx_setup_phy(ehci, pda=
ta->phy_mode, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ehci_fsl_setup_phy(ehci, pd=
ata->phy_mode, 0);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (pdata->port_enables & FSL_USB2_PORT1_E=
NABLED)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 mpc83xx_setup_phy(ehci, pda=
ta->phy_mode, 1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ehci_fsl_setup_phy(ehci, pd=
ata->phy_mode, 1);
> =A0 =A0 =A0 =A0}
>
> =A0 =A0 =A0 =A0/* put controller in host mode. */
> - =A0 =A0 =A0 ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMOD=
E);
> + =A0 =A0 =A0 tmp =3D USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0);
> + =A0 =A0 =A0 ehci_writel(ehci, tmp, non_ehci + FSL_SOC_USB_USBMODE);
> +
> + =A0 =A0 =A0 if (pdata->have_sysif_regs) {
> =A0#ifdef CONFIG_PPC_85xx
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x=
00000008);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH=
, 0x00000080);
> =A0#else
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x=
0000000c);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH=
, 0x00000040);
> =A0#endif
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x0=
0000001);
> + =A0 =A0 =A0 }
> =A0}
Unrelated whitespace changes. Put in separate patch.
>
> =A0/* called after powerup, by probe or system-pm "wakeup" */
> =A0static int ehci_fsl_reinit(struct ehci_hcd *ehci)
> =A0{
> - =A0 =A0 =A0 mpc83xx_usb_setup(ehci_to_hcd(ehci));
> + =A0 =A0 =A0 ehci_fsl_usb_setup(ehci);
> =A0 =A0 =A0 =A0ehci_port_power(ehci, 0);
>
> =A0 =A0 =A0 =A0return 0;
> @@ -259,6 +304,11 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
> =A0{
> =A0 =A0 =A0 =A0struct ehci_hcd *ehci =3D hcd_to_ehci(hcd);
> =A0 =A0 =A0 =A0int retval;
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata;
> +
> + =A0 =A0 =A0 pdata =3D hcd->self.controller->platform_data;
> + =A0 =A0 =A0 ehci->big_endian_desc =3D pdata->big_endian_desc;
> + =A0 =A0 =A0 ehci->big_endian_mmio =3D pdata->big_endian_mmio;
>
> =A0 =A0 =A0 =A0/* EHCI registers start at offset 0x100 */
> =A0 =A0 =A0 =A0ehci->caps =3D hcd->regs + 0x100;
> @@ -369,7 +419,7 @@ static const struct hc_driver ehci_fsl_hc_driver =3D =
{
> =A0 =A0 =A0 =A0 * generic hardware linkage
> =A0 =A0 =A0 =A0 */
> =A0 =A0 =A0 =A0.irq =3D ehci_irq,
> - =A0 =A0 =A0 .flags =3D HCD_USB2,
> + =A0 =A0 =A0 .flags =3D HCD_USB2 | HCD_MEMORY,
>
> =A0 =A0 =A0 =A0/*
> =A0 =A0 =A0 =A0 * basic lifecycle operations
> diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
> index b5e59db..3525bb4 100644
> --- a/drivers/usb/host/ehci-fsl.h
> +++ b/drivers/usb/host/ehci-fsl.h
> @@ -1,4 +1,4 @@
> -/* Copyright (c) 2005 freescale semiconductor
> +/* Copyright (C) 2005-2009 Freescale Semiconductor, Inc. All rights rese=
rved.
> =A0* Copyright (c) 2005 MontaVista Software
> =A0*
> =A0* This program is free software; you can redistribute =A0it and/or mod=
ify it
> @@ -19,6 +19,11 @@
> =A0#define _EHCI_FSL_H
>
> =A0/* offsets for the non-ehci registers in the FSL SOC USB controller */
> +#define FSL_SOC_USB_ID =A0 =A0 =A0 =A0 0x0
> +#define ID_MSK =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0x3f
> +#define NID_MSK =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A00x3f00
> +#define FSL_SOC_USB_SBUSCFG =A0 =A00x90
> +#define FSL_SOC_USB_BURSTSIZE =A00x160
> =A0#define FSL_SOC_USB_ULPIVP =A0 =A0 0x170
> =A0#define FSL_SOC_USB_PORTSC1 =A0 =A00x184
> =A0#define PORT_PTS_MSK =A0 =A0 =A0 =A0 =A0 (3<<30)
> @@ -26,8 +31,20 @@
> =A0#define PORT_PTS_ULPI =A0 =A0 =A0 =A0 =A0(2<<30)
> =A0#define =A0 =A0 =A0 =A0PORT_PTS_SERIAL =A0 =A0 =A0 =A0 (3<<30)
> =A0#define PORT_PTS_PTW =A0 =A0 =A0 =A0 =A0 (1<<28)
> +#define PORT_PTS_PHCD =A0 =A0 =A0 =A0 =A0(1<<23)
> =A0#define FSL_SOC_USB_PORTSC2 =A0 =A00x188
> =A0#define FSL_SOC_USB_USBMODE =A0 =A00x1a8
> +#define USBMODE_CM_MASK =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(3 << 0) =A0 =A0 =
=A0 =A0/* controller mode mask */
> +#define USBMODE_CM_HOST =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(3 << 0) =A0 =A0 =
=A0 =A0/* controller mode: host */
> +#define USBMODE_ES =A0 =A0 =A0 =A0 =A0 =A0 (1 << 2) =A0 =A0 =A0 =A0/* (B=
ig) Endian Select */
> +
> +#define FSL_SOC_USB_USBGENCTRL =A0 =A0 =A0 =A0 0x200
> +#define USBGENCTRL_PPP =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 3)
> +#define USBGENCTRL_PFP =A0 =A0 =A0 =A0 (1 << 2)
> +#define FSL_SOC_USB_ISIPHYCTRL 0x204
> +#define ISIPHYCTRL_PXE =A0 =A0 =A0 =A0 (1)
> +#define ISIPHYCTRL_PHYE =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 4)
> +
> =A0#define FSL_SOC_USB_SNOOP1 =A0 =A0 0x400 =A0 /* NOTE: big-endian */
> =A0#define FSL_SOC_USB_SNOOP2 =A0 =A0 0x404 =A0 /* NOTE: big-endian */
> =A0#define FSL_SOC_USB_AGECNTTHRSH =A0 =A0 =A0 =A00x408 =A0 /* NOTE: big-=
endian */
> diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
> index aeda96e..1e7e004 100644
> --- a/drivers/usb/host/ehci-mem.c
> +++ b/drivers/usb/host/ehci-mem.c
> @@ -40,7 +40,7 @@ static inline void ehci_qtd_init(struct ehci_hcd *ehci,=
struct ehci_qtd *qtd,
> =A0{
> =A0 =A0 =A0 =A0memset (qtd, 0, sizeof *qtd);
> =A0 =A0 =A0 =A0qtd->qtd_dma =3D dma;
> - =A0 =A0 =A0 qtd->hw_token =3D cpu_to_le32 (QTD_STS_HALT);
> + =A0 =A0 =A0 qtd->hw_token =3D cpu_to_hc32(ehci, QTD_STS_HALT);
> =A0 =A0 =A0 =A0qtd->hw_next =3D EHCI_LIST_END(ehci);
> =A0 =A0 =A0 =A0qtd->hw_alt_next =3D EHCI_LIST_END(ehci);
> =A0 =A0 =A0 =A0INIT_LIST_HEAD (&qtd->qtd_list);
> diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
> index 28e33fe..dfe603f 100644
> --- a/include/linux/fsl_devices.h
> +++ b/include/linux/fsl_devices.h
> @@ -58,11 +58,21 @@ enum fsl_usb2_phy_modes {
> =A0 =A0 =A0 =A0FSL_USB2_PHY_SERIAL,
> =A0};
>
> +struct platform_device;
> =A0struct fsl_usb2_platform_data {
> =A0 =A0 =A0 =A0/* board specific information */
> =A0 =A0 =A0 =A0enum fsl_usb2_operating_modes =A0 operating_mode;
> =A0 =A0 =A0 =A0enum fsl_usb2_phy_modes =A0 =A0 =A0 =A0 phy_mode;
> =A0 =A0 =A0 =A0unsigned int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0port_e=
nables;
> +
> + =A0 =A0 =A0 char =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0*name; =A0 =A0 =A0 =A0 =A0/* pretty print */
> + =A0 =A0 =A0 int (*platform_init) (struct platform_device *);
> + =A0 =A0 =A0 void (*platform_uninit) (struct platform_device *);
> + =A0 =A0 =A0 void __iomem =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*regs; =
=A0/* ioremap'd register base */
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0big=
_endian_mmio:1;
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0big=
_endian_desc:1;
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0es:=
1; =A0 =A0 =A0 =A0 =A0 /* need USBMODE:ES */
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0hav=
e_sysif_regs:1;
> =A0};
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH 07/11] dma: Add MPC512x DMA driver
From: Grant Likely @ 2010-01-21 17:22 UTC (permalink / raw)
To: Anatolij Gustschin; +Cc: wd, dzu, linuxppc-dev, Dan Williams, Piotr Ziecik
In-Reply-To: <1263932653-3634-8-git-send-email-agust@denx.de>
On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust@denx.de> wrote:
> From: Piotr Ziecik <kosmo@semihalf.com>
>
> Adds initial version of MPC512x DMA driver.
> Only memory to memory transfers are currenly supported.
Comments below on brief review. I've not looked at the code in-depth.
> Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
> Signed-off-by: Wolfgang Denk <wd@denx.de>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: John Rigby <jcrigby@gmail.com>
> ---
> =A0drivers/dma/Kconfig =A0 =A0 =A0 | =A0 =A07 +
> =A0drivers/dma/Makefile =A0 =A0 =A0| =A0 =A01 +
> =A0drivers/dma/mpc512x_dma.c | =A0636 +++++++++++++++++++++++++++++++++++=
++++++++++
> =A0drivers/dma/mpc512x_dma.h | =A0192 ++++++++++++++
Unless the stuff in the .h file is used by other .c files, it really
belongs in mpc512x_dma.c
> +static int __init mpc_dma_probe(struct of_device *op,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 const struct of_device_id *match)
__devinit
> +static void __exit mpc_dma_remove(struct of_device *op)
__devexit
> +{
> + =A0 =A0 =A0 struct device *dev =3D &op->dev;
> + =A0 =A0 =A0 struct mpc_dma *mdma =3D dev_get_drvdata(dev);
> +
> + =A0 =A0 =A0 devm_free_irq(dev, mdma->irq, mdma);
> +}
No unregistration of the dma device? No unmapping? No kfree()?
> +
> +static struct of_device_id mpc_dma_match[] =3D {
> + =A0 =A0 =A0 { .compatible =3D "fsl,mpc5121-dma", },
> + =A0 =A0 =A0 {},
> +};
> +
> +static struct of_platform_driver mpc_dma_driver =3D {
> + =A0 =A0 =A0 .match_table =A0 =A0=3D mpc_dma_match,
> + =A0 =A0 =A0 .probe =A0 =A0 =A0 =A0 =A0=3D mpc_dma_probe,
> + =A0 =A0 =A0 .remove =A0 =A0 =A0 =A0 =3D __exit_p(mpc_dma_remove),
__devexit_p()
> + =A0 =A0 =A0 .driver =A0 =A0 =A0 =A0 =3D {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .name =A0 =3D DRV_NAME,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .owner =A0=3D THIS_MODULE,
> + =A0 =A0 =A0 },
> +};
> +
> +static int __init mpc_dma_init(void)
> +{
> + =A0 =A0 =A0 return of_register_platform_driver(&mpc_dma_driver);
> +}
> +module_init(mpc_dma_init);
> +
> +static void __exit mpc_dma_exit(void)
> +{
> + =A0 =A0 =A0 of_unregister_platform_driver(&mpc_dma_driver);
> +}
> +module_exit(mpc_dma_exit);
> +
> +/* MODULE API */
Meaningless comment.
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Piotr Ziecik <kosmo@semihalf.com>");
Thanks,
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support
From: Grant Likely @ 2010-01-21 17:12 UTC (permalink / raw)
To: Anatolij Gustschin; +Cc: wd, dzu, linuxppc-dev, linux-i2c, Piotr Ziecik
In-Reply-To: <1263932653-3634-5-git-send-email-agust@denx.de>
On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust@denx.de> wrote:
> From: Piotr Ziecik <kosmo@semihalf.com>
>
> =A0 =A0- Update Kconfig for i2c-mpc driver.
> =A0 =A0- Enable I2C interrupts on MPC5121.
>
> diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
> index f627001..84eeb25 100644
> --- a/drivers/i2c/busses/i2c-mpc.c
> +++ b/drivers/i2c/busses/i2c-mpc.c
> @@ -540,6 +540,29 @@ static int __devinit fsl_i2c_probe(struct of_device =
*op,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0}
>
> + =A0 =A0 =A0 if (of_device_is_compatible(op->node, "fsl,mpc5121-i2c")) {
Rather than doing stuff like this with explicit compatible checks in
the probe hook, consider using the .data pointer in the of match
table.
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [net-next-2.6 PATCH 3/3] fs_enet: Add FEC TX Alignment workaround for MPC5121
From: Grant Likely @ 2010-01-21 16:49 UTC (permalink / raw)
To: Anatolij Gustschin; +Cc: wd, dzu, netdev, linuxppc-dev, Piotr Ziecik
In-Reply-To: <1264039999-25731-4-git-send-email-agust@denx.de>
On Wed, Jan 20, 2010 at 7:13 PM, Anatolij Gustschin <agust@denx.de> wrote:
> The FEC on 5121 has problems with misaligned tx buffers.
> The RM says any alignment is ok but empirical results
> show that packet buffers ending in 0x1E will sometimes
> hang the FEC. =A0Other bad alignment does not hang but will
> cause silent TX failures resulting in about a 1% packet
> loss as tested by ping -f from a remote host.
>
> This patch is a work around that copies every tx packet
> to an aligned skb before sending.
>
> Signed-off-by: John Rigby <jcrigby@gmail.com>
> Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
> Signed-off-by: Wolfgang Denk <wd@denx.de>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: <linuxppc-dev@ozlabs.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> ---
> Changes since previous submited version:
>
> - don't use printk any more and use dev_warn().
>
> =A0drivers/net/fs_enet/fs_enet-main.c | =A0 38 ++++++++++++++++++++++++++=
++++++++++
> =A01 files changed, 38 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_=
enet-main.c
> index 6bce5c8..7f0bd5d 100644
> --- a/drivers/net/fs_enet/fs_enet-main.c
> +++ b/drivers/net/fs_enet/fs_enet-main.c
> @@ -580,6 +580,32 @@ void fs_cleanup_bds(struct net_device *dev)
>
> =A0/*********************************************************************=
*************/
>
> +static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0 =A0 =A0struct sk_buff *skb)
> +{
> + =A0 =A0 =A0 struct sk_buff *new_skb;
> + =A0 =A0 =A0 struct fs_enet_private *fep =3D netdev_priv(dev);
> +
> + =A0 =A0 =A0 /* Alloc new skb */
> + =A0 =A0 =A0 new_skb =3D dev_alloc_skb(ENET_RX_FRSIZE + 32);
> + =A0 =A0 =A0 if (!new_skb) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(fep->dev, "Memory squeeze, droppin=
g tx packet.\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return NULL;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Make sure new skb is properly aligned */
> + =A0 =A0 =A0 skb_align(new_skb, 32);
> +
> + =A0 =A0 =A0 /* Copy data to new skb ... */
> + =A0 =A0 =A0 skb_copy_from_linear_data(skb, new_skb->data, skb->len);
> + =A0 =A0 =A0 skb_put(new_skb, skb->len);
> +
> + =A0 =A0 =A0 /* ... and free an old one */
> + =A0 =A0 =A0 dev_kfree_skb_any(skb);
> +
> + =A0 =A0 =A0 return new_skb;
> +}
This looks expensive. It's allocating a new skb on *every* packet
transmission, rather than just on the ones that fail the alignment
condition.
> +
> =A0static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *=
dev)
> =A0{
> =A0 =A0 =A0 =A0struct fs_enet_private *fep =3D netdev_priv(dev);
> @@ -588,6 +614,18 @@ static int fs_enet_start_xmit(struct sk_buff *skb, s=
truct net_device *dev)
> =A0 =A0 =A0 =A0u16 sc;
> =A0 =A0 =A0 =A0unsigned long flags;
>
> + =A0 =A0 =A0 if (fep->fec.fec_id =3D=3D FS_ENET_MPC5121_FEC) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb =3D tx_skb_align_workaround(dev, skb);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!skb) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* We have lost packet du=
e to memory allocation error
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* in tx_skb_align_workar=
ound(). Hopefully original skb
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* is still valid, so try=
transmit it later.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return NETDEV_TX_BUSY;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +
Rather than performing this test every time through on a fast path,
consider creating a new start_xmit hook and registering the correct
one in the ops structure at probe time.
> =A0 =A0 =A0 =A0spin_lock_irqsave(&fep->tx_lock, flags);
>
> =A0 =A0 =A0 =A0/*
> --
> 1.5.6.3
>
>
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [net-next-2.6 PATCH 1/3] fs_enet: use dev_xxx instead of printk
From: Grant Likely @ 2010-01-21 16:43 UTC (permalink / raw)
To: Anatolij Gustschin; +Cc: Piotr Ziecik, dzu, netdev, linuxppc-dev, wd
In-Reply-To: <1264039999-25731-2-git-send-email-agust@denx.de>
On Wed, Jan 20, 2010 at 7:13 PM, Anatolij Gustschin <agust@denx.de> wrote:
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: <linuxppc-dev@ozlabs.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
> Cc: John Rigby <jcrigby@gmail.com>
> Cc: Piotr Ziecik <kosmo@semihalf.com>
> Cc: Wolfgang Denk <wd@denx.de>
> ---
> =A0drivers/net/fs_enet/fs_enet-main.c | =A0 39 +++++++++++++-------------=
---------
> =A0drivers/net/fs_enet/mac-fcc.c =A0 =A0 =A0| =A0 =A05 ++-
> =A0drivers/net/fs_enet/mac-fec.c =A0 =A0 =A0| =A0 12 ++++------
> =A0drivers/net/fs_enet/mac-scc.c =A0 =A0 =A0| =A0 =A09 +++----
> =A04 files changed, 27 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_=
enet-main.c
> index ec2f503..c34a7e0 100644
> --- a/drivers/net/fs_enet/fs_enet-main.c
> +++ b/drivers/net/fs_enet/fs_enet-main.c
> @@ -108,9 +108,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, =
int budget)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * the last indicator should be set.
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if ((sc & BD_ENET_RX_LAST) =3D=3D 0)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_WARNING DRV_MOD=
ULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0": %s rcv is=
not +last\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev->name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(fep->dev, "rcv is =
not +last\n");
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/*
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * Check for errors.
> @@ -178,9 +176,8 @@ static int fs_enet_rx_napi(struct napi_struct *napi, =
int budget)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0received++=
;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0netif_rece=
ive_skb(skb);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN=
_WARNING DRV_MODULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0": %s Memory squeeze, dropping packet.\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0dev->name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(fe=
p->dev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0"Memory squeeze, dropping packet.\n");
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0fep->stats=
.rx_dropped++;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0skbn =3D s=
kb;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> @@ -242,9 +239,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev=
)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * the last indicator should be set.
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if ((sc & BD_ENET_RX_LAST) =3D=3D 0)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_WARNING DRV_MOD=
ULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0": %s rcv is=
not +last\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev->name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(fep->dev, "rcv is =
not +last\n");
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/*
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * Check for errors.
> @@ -313,9 +308,8 @@ static int fs_enet_rx_non_napi(struct net_device *dev=
)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0received++=
;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0netif_rx(s=
kb);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN=
_WARNING DRV_MODULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0": %s Memory squeeze, dropping packet.\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0dev->name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(fe=
p->dev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0"Memory squeeze, dropping packet.\n");
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0fep->stats=
.rx_dropped++;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0skbn =3D s=
kb;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> @@ -388,10 +382,10 @@ static void fs_enet_tx(struct net_device *dev)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0fep->stats.tx_packets++;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (sc & BD_ENET_TX_READY)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_WARNING DRV_MOD=
ULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0": %s HEY! E=
net xmit interrupt and TX_READY.\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev->name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (sc & BD_ENET_TX_READY) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(fep->dev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"HEY! En=
et xmit interrupt and TX_READY.\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/*
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * Deferred means some collisions occurred=
during transmit,
> @@ -511,9 +505,8 @@ void fs_init_bds(struct net_device *dev)
> =A0 =A0 =A0 =A0for (i =3D 0, bdp =3D fep->rx_bd_base; i < fep->rx_ring; i=
++, bdp++) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0skb =3D dev_alloc_skb(ENET_RX_FRSIZE);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (skb =3D=3D NULL) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_WARNING DRV_MOD=
ULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0": %s Memory=
squeeze, unable to allocate skb\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev->name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(fep->dev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"Memory =
squeeze, unable to allocate skb\n");
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0skb_align(skb, ENET_RX_ALIGN);
> @@ -610,8 +603,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, st=
ruct net_device *dev)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * Ooops. =A0All transmit buffers are full=
. =A0Bail out.
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * This should not happen, since the tx qu=
eue should be stopped.
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_WARNING DRV_MODULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0": %s tx queue full!.\n", de=
v->name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(fep->dev, "tx queue full!.\n");
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return NETDEV_TX_BUSY;
> =A0 =A0 =A0 =A0}
>
> @@ -788,8 +780,7 @@ static int fs_enet_open(struct net_device *dev)
> =A0 =A0 =A0 =A0r =3D request_irq(fep->interrupt, fs_enet_interrupt, IRQF_=
SHARED,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"fs_enet-mac", dev);
> =A0 =A0 =A0 =A0if (r !=3D 0) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_ERR DRV_MODULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0": %s Could not allocate FS_=
ENET IRQ!", dev->name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(fep->dev, "Could not allocate FS_EN=
ET IRQ!");
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (fep->fpi->use_napi)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0napi_disable(&fep->napi);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return -EINVAL;
> @@ -1053,7 +1044,7 @@ static int __devinit fs_enet_probe(struct of_device=
*ofdev,
> =A0 =A0 =A0 =A0if (ret)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto out_free_bd;
>
> - =A0 =A0 =A0 printk(KERN_INFO "%s: fs_enet: %pM\n", ndev->name, ndev->de=
v_addr);
> + =A0 =A0 =A0 pr_info("%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr);
>
> =A0 =A0 =A0 =A0return 0;
>
> diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.=
c
> index 22e5a84..dd78640 100644
> --- a/drivers/net/fs_enet/mac-fcc.c
> +++ b/drivers/net/fs_enet/mac-fcc.c
> @@ -476,8 +476,9 @@ static void clear_int_events(struct net_device *dev, =
u32 int_events)
>
> =A0static void ev_error(struct net_device *dev, u32 int_events)
> =A0{
> - =A0 =A0 =A0 printk(KERN_WARNING DRV_MODULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0": %s FS_ENET ERROR(s) 0x%x\n", dev->name, i=
nt_events);
> + =A0 =A0 =A0 struct fs_enet_private *fep =3D netdev_priv(dev);
> +
> + =A0 =A0 =A0 dev_warn(fep->dev, "FS_ENET ERROR(s) 0x%x\n", int_events);
> =A0}
>
> =A0static int get_regs(struct net_device *dev, void *p, int *sizep)
> diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.=
c
> index ca7bcb8..a664aa1 100644
> --- a/drivers/net/fs_enet/mac-fec.c
> +++ b/drivers/net/fs_enet/mac-fec.c
> @@ -257,8 +257,7 @@ static void restart(struct net_device *dev)
>
> =A0 =A0 =A0 =A0r =3D whack_reset(fep->fec.fecp);
> =A0 =A0 =A0 =A0if (r !=3D 0)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_ERR DRV_MODULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ": %s FEC R=
eset FAILED!\n", dev->name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(fep->dev, "FEC Reset FAILED!\n");
> =A0 =A0 =A0 =A0/*
> =A0 =A0 =A0 =A0 * Set station address.
> =A0 =A0 =A0 =A0 */
> @@ -355,9 +354,7 @@ static void stop(struct net_device *dev)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0udelay(1);
>
> =A0 =A0 =A0 =A0if (i =3D=3D FEC_RESET_DELAY)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_WARNING DRV_MODULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0": %s FEC timeout on gracefu=
l transmit stop\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev->name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(fep->dev, "FEC timeout on graceful=
transmit stop\n");
> =A0 =A0 =A0 =A0/*
> =A0 =A0 =A0 =A0 * Disable FEC. Let only MII interrupts.
> =A0 =A0 =A0 =A0 */
> @@ -433,8 +430,9 @@ static void clear_int_events(struct net_device *dev, =
u32 int_events)
>
> =A0static void ev_error(struct net_device *dev, u32 int_events)
> =A0{
> - =A0 =A0 =A0 printk(KERN_WARNING DRV_MODULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0": %s FEC ERROR(s) 0x%x\n", dev->name, int_e=
vents);
> + =A0 =A0 =A0 struct fs_enet_private *fep =3D netdev_priv(dev);
> +
> + =A0 =A0 =A0 dev_warn(fep->dev, "FEC ERROR(s) 0x%x\n", int_events);
> =A0}
>
> =A0static int get_regs(struct net_device *dev, void *p, int *sizep)
> diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.=
c
> index 008cdd9..2d8917f 100644
> --- a/drivers/net/fs_enet/mac-scc.c
> +++ b/drivers/net/fs_enet/mac-scc.c
> @@ -367,9 +367,7 @@ static void stop(struct net_device *dev)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0udelay(1);
>
> =A0 =A0 =A0 =A0if (i =3D=3D SCC_RESET_DELAY)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_WARNING DRV_MODULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0": %s SCC timeout on gracefu=
l transmit stop\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev->name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(fep->dev, "SCC timeout on graceful=
transmit stop\n");
>
> =A0 =A0 =A0 =A0W16(sccp, scc_sccm, 0);
> =A0 =A0 =A0 =A0C32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
> @@ -429,8 +427,9 @@ static void clear_int_events(struct net_device *dev, =
u32 int_events)
>
> =A0static void ev_error(struct net_device *dev, u32 int_events)
> =A0{
> - =A0 =A0 =A0 printk(KERN_WARNING DRV_MODULE_NAME
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0": %s SCC ERROR(s) 0x%x\n", dev->name, int_e=
vents);
> + =A0 =A0 =A0 struct fs_enet_private *fep =3D netdev_priv(dev);
> +
> + =A0 =A0 =A0 dev_warn(fep->dev, "SCC ERROR(s) 0x%x\n", int_events);
> =A0}
>
> =A0static int get_regs(struct net_device *dev, void *p, int *sizep)
> --
> 1.5.6.3
>
>
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: How to trun off udbg0 during bootup?
From: Peter Korsgaard @ 2010-01-21 15:34 UTC (permalink / raw)
To: 景文林; +Cc: linuxppc-dev
In-Reply-To: <b90a809a1001201702y7d42eb60v43f24cb1043a89fa@mail.gmail.com>
>>>>> "=E6=99=AF=E6=96=87=E6=9E=97" =3D=3D =E6=99=AF=E6=96=87=E6=9E=97 <we=
nlinjing@gmail.com> writes:
=E6=99=AF=E6=96=87=E6=9E=97> Hi,
=E6=99=AF=E6=96=87=E6=9E=97> =C2=A0I `m working on a freescale-MPC8379eRDB=
like board.And I want
=E6=99=AF=E6=96=87=E6=9E=97> to trun off kernel message during bootup.
=E6=99=AF=E6=96=87=E6=9E=97> =C2=A0I tried to=C2=A0 modify "console =3D XX=
X" argument in uboot but it
=E6=99=AF=E6=96=87=E6=9E=97> did not work(It works on ARM). Kernel always =
print:
=E6=99=AF=E6=96=87=E6=9E=97> "console [udbg0] enabled" =C2=A0=C2=A0 or=C2=
=A0=C2=A0 "console handover: boot
=E6=99=AF=E6=96=87=E6=9E=97> [udbg0] -> real [ttyS1]"=C2=A0
=E6=99=AF=E6=96=87=E6=9E=97> Does anybody know how can I turn off this udb=
g0?
It's currently not configurable. I sent a (not applied) patch to make it
configurable back in Dec 2008:
http://lists.ozlabs.org/pipermail/linuxppc-dev/2008-December/066461.html
You can probably still get it to apply with a bit of fuzz.
--=20
Bye, Peter Korsgaard
^ permalink raw reply
* Re: [net-next-2.6 PATCH 2/3] fs_enet: Add support for MPC512x to fs_enet driver
From: Wolfgang Grandegger @ 2010-01-21 15:25 UTC (permalink / raw)
To: David Miller; +Cc: wd, dzu, netdev, linuxppc-dev, agust, kosmo
In-Reply-To: <20100121.012235.161201297.davem@davemloft.net>
David Miller wrote:
> From: Anatolij Gustschin <agust@denx.de>
> Date: Thu, 21 Jan 2010 03:13:18 +0100
>
>> struct fec_info {
>> - fec_t __iomem *fecp;
>> + void __iomem *fecp;
To avoid confusion, the name "base_addr" seems more appropriate as it's
just used to calculate register offsets and for iomap/unmap.
> ...
>> /* write */
>> -#define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fec_ ## _reg, (_v))
>> +#define FW(_regp, _reg, _v) __fs_out32((_regp)->fec_ ## _reg, (_v))
> ...
>> +/* register address macros */
>> +#define fec_reg_addr(_type, _reg) \
>> + (fep->fec.rtbl->fec_##_reg = (u32 __iomem *)((u32)fep->fec.fecp + \
>> + (u32)&((__typeof__(_type) *)NULL)->fec_##_reg))
>> +
>> +#define fec_reg_mpc8xx(_reg) \
>> + fec_reg_addr(struct mpc8xx_fec, _reg)
>> +
>> +#define fec_reg_mpc5121(_reg) \
>> + fec_reg_addr(struct mpc5121_fec, _reg)
>
> This is a step backwards in my view.
>
> If you use the "fec_t __iomem *" type for the register
> pointer, you simply use &p->fecp->XXX to get the I/O
> address of register XXX and that's what you pass to
> the appropriate I/O accessor routines.
>
> Now you've made it typeless, and then you have to walk
> through all of these contortions to get the offset.
>
> I don't want to apply this, sorry...
The major problem that Anatolij tries to solve are the different
register layouts of the supported SOCs, MPC52xx and MPC8xx. They use the
same registers but at *different* offsets. Therefore we cannot handle
this with a single "fec_t" struct to allow building a single kernel
image. Instead it's handled by filling a table with register addresses:
if (of_device_is_compatible(ofdev->node, "fsl,mpc5121-fec")) {
fep->fec.fec_id = FS_ENET_MPC5121_FEC;
fec_reg_mpc5121(ievent);
fec_reg_mpc5121(imask);
...
} else {
fec_reg_mpc8xx(ievent);
fec_reg_mpc8xx(imask);
...
}
Do you see a more clever solution to this problem? Nevertheless, the
code could be improved by using "offsetof", I think.
Wolfgang.
^ permalink raw reply
* Re: [net-next-2.6 PATCH 2/3] fs_enet: Add support for MPC512x to fs_enet driver
From: Anatolij Gustschin @ 2010-01-21 9:33 UTC (permalink / raw)
To: David Miller; +Cc: wd, dzu, netdev, linuxppc-dev, kosmo
In-Reply-To: <20100121.012235.161201297.davem@davemloft.net>
On Thu, 21 Jan 2010 01:22:35 -0800 (PST)
David Miller <davem@davemloft.net> wrote:
> From: Anatolij Gustschin <agust@denx.de>
> Date: Thu, 21 Jan 2010 03:13:18 +0100
>
> > struct fec_info {
> > - fec_t __iomem *fecp;
> > + void __iomem *fecp;
> ...
> > /* write */
> > -#define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fec_ ## _reg, (_v))
> > +#define FW(_regp, _reg, _v) __fs_out32((_regp)->fec_ ## _reg, (_v))
> ...
> > +/* register address macros */
> > +#define fec_reg_addr(_type, _reg) \
> > + (fep->fec.rtbl->fec_##_reg = (u32 __iomem *)((u32)fep->fec.fecp + \
> > + (u32)&((__typeof__(_type) *)NULL)->fec_##_reg))
> > +
> > +#define fec_reg_mpc8xx(_reg) \
> > + fec_reg_addr(struct mpc8xx_fec, _reg)
> > +
> > +#define fec_reg_mpc5121(_reg) \
> > + fec_reg_addr(struct mpc5121_fec, _reg)
>
> This is a step backwards in my view.
>
> If you use the "fec_t __iomem *" type for the register
> pointer, you simply use &p->fecp->XXX to get the I/O
> address of register XXX and that's what you pass to
> the appropriate I/O accessor routines.
>
> Now you've made it typeless, and then you have to walk
> through all of these contortions to get the offset.
OK, i give up
^ permalink raw reply
* Re: [net-next-2.6 PATCH 2/3] fs_enet: Add support for MPC512x to fs_enet driver
From: David Miller @ 2010-01-21 9:22 UTC (permalink / raw)
To: agust; +Cc: wd, dzu, netdev, linuxppc-dev, kosmo
In-Reply-To: <1264039999-25731-3-git-send-email-agust@denx.de>
From: Anatolij Gustschin <agust@denx.de>
Date: Thu, 21 Jan 2010 03:13:18 +0100
> struct fec_info {
> - fec_t __iomem *fecp;
> + void __iomem *fecp;
...
> /* write */
> -#define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fec_ ## _reg, (_v))
> +#define FW(_regp, _reg, _v) __fs_out32((_regp)->fec_ ## _reg, (_v))
...
> +/* register address macros */
> +#define fec_reg_addr(_type, _reg) \
> + (fep->fec.rtbl->fec_##_reg = (u32 __iomem *)((u32)fep->fec.fecp + \
> + (u32)&((__typeof__(_type) *)NULL)->fec_##_reg))
> +
> +#define fec_reg_mpc8xx(_reg) \
> + fec_reg_addr(struct mpc8xx_fec, _reg)
> +
> +#define fec_reg_mpc5121(_reg) \
> + fec_reg_addr(struct mpc5121_fec, _reg)
This is a step backwards in my view.
If you use the "fec_t __iomem *" type for the register
pointer, you simply use &p->fecp->XXX to get the I/O
address of register XXX and that's what you pass to
the appropriate I/O accessor routines.
Now you've made it typeless, and then you have to walk
through all of these contortions to get the offset.
I don't want to apply this, sorry...
^ permalink raw reply
* Re: [PATCH 4/4] phy: add RTBI mode for m88e1111
From: David Miller @ 2010-01-21 9:18 UTC (permalink / raw)
To: B13201; +Cc: netdev, linuxppc-dev
In-Reply-To: <0A1FE637C2C7E148B9573BB60CC630E5711B54@zch01exm26.fsl.freescale.net>
From: "Liu Yu-B13201" <B13201@freescale.com>
Date: Fri, 15 Jan 2010 10:49:37 +0800
>> -----Original Message-----
>> From: Kumar Gala [mailto:galak@kernel.crashing.org]
>> Sent: Friday, January 15, 2010 12:20 AM
>> To: Liu Yu-B13201
>> Cc: davem@davemloft.net; linuxppc-dev@lists.ozlabs.org;
>> netdev@vger.kernel.org
>> Subject: Re: [PATCH 4/4] phy: add RTBI mode for m88e1111
>>
>>
>> Does this magic 0x7 have some meaning?
>>
>
> Hrr... it's GMII to fibre mode.
> Document 88E1111_erata_RevB2 chapter 4.35 describ the reason.
> Without this sometimes phys couldnot work.
Just FYI, I've applied all of these patches to net-next-2.6
^ permalink raw reply
* [Patch 1/1] PPC64-HWBKPT: Implement hw-breakpoints for PPC64
From: K.Prasad @ 2010-01-21 8:49 UTC (permalink / raw)
To: linuxppc-dev, David Gibson, Roland McGrath
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, Alan Stern, paulus
In-Reply-To: <20100121084640.GA3252@in.ibm.com>
Implement perf-events based hw-breakpoint interfaces for PPC64 processors.
These interfaces help arbitrate requests from various users and schedules
them as appropriate.
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
arch/powerpc/Kconfig | 1
arch/powerpc/include/asm/hw_breakpoint.h | 55 ++++
arch/powerpc/include/asm/processor.h | 6
arch/powerpc/include/asm/reg.h | 1
arch/powerpc/kernel/Makefile | 2
arch/powerpc/kernel/hw_breakpoint.c | 363 +++++++++++++++++++++++++++++++
arch/powerpc/kernel/process.c | 5
arch/powerpc/kernel/ptrace.c | 77 ++++++
arch/powerpc/mm/fault.c | 14 -
9 files changed, 515 insertions(+), 9 deletions(-)
Index: linux-2.6-tip.new_ppc64_perf/arch/powerpc/include/asm/hw_breakpoint.h
===================================================================
--- /dev/null
+++ linux-2.6-tip.new_ppc64_perf/arch/powerpc/include/asm/hw_breakpoint.h
@@ -0,0 +1,55 @@
+#ifndef _PPC64_HW_BREAKPOINT_H
+#define _PPC64_HW_BREAKPOINT_H
+
+#ifdef __KERNEL__
+#define __ARCH_HW_BREAKPOINT_H
+#ifdef CONFIG_PPC64
+
+struct arch_hw_breakpoint {
+ u8 len; /* length of the target symbol */
+ int type;
+ char *name; /* Contains name of the symbol to set bkpt */
+ unsigned long address;
+};
+
+#include <linux/kdebug.h>
+#include <asm/reg.h>
+#include <asm/system.h>
+
+/* Total number of available HW breakpoint registers */
+#define HBP_NUM 1
+
+struct perf_event;
+struct pmu;
+struct perf_sample_data;
+
+#define HW_BREAKPOINT_ALIGN 0x7
+/* Maximum permissible length of any HW Breakpoint */
+#define HW_BREAKPOINT_LEN 0x8
+
+extern int arch_validate_hwbkpt_settings(struct perf_event *bp,
+ struct task_struct *tsk);
+extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+ unsigned long val, void *data);
+int arch_install_hw_breakpoint(struct perf_event *bp);
+void arch_uninstall_hw_breakpoint(struct perf_event *bp);
+void hw_breakpoint_pmu_read(struct perf_event *bp);
+void hw_breakpoint_pmu_unthrottle(struct perf_event *bp);
+extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
+
+extern struct pmu perf_ops_bp;
+extern void ptrace_triggered(struct perf_event *bp, int nmi,
+ struct perf_sample_data *data, struct pt_regs *regs);
+static inline void hw_breakpoint_disable(void)
+{
+ set_dabr(0);
+}
+
+#else
+static inline void hw_breakpoint_disable(void)
+{
+ /* Function is defined only on PPC64 for now */
+}
+#endif /* CONFIG_PPC64 */
+#endif /* __KERNEL__ */
+#endif /* _PPC64_HW_BREAKPOINT_H */
Index: linux-2.6-tip.new_ppc64_perf/arch/powerpc/kernel/hw_breakpoint.c
===================================================================
--- /dev/null
+++ linux-2.6-tip.new_ppc64_perf/arch/powerpc/kernel/hw_breakpoint.c
@@ -0,0 +1,363 @@
+/*
+ * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
+ * using the CPU's debug registers. Derived from
+ * "arch/x86/kernel/hw_breakpoint.c"
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright 2009 IBM Corporation
+ * Author: K.Prasad <prasad@linux.vnet.ibm.com>
+ *
+ */
+
+#include <linux/hw_breakpoint.h>
+#include <linux/notifier.h>
+#include <linux/kprobes.h>
+#include <linux/percpu.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+
+#include <asm/hw_breakpoint.h>
+#include <asm/processor.h>
+#include <asm/sstep.h>
+
+/*
+ * Store the 'bp' that caused the hw-breakpoint exception just before we
+ * single-step. Used to distinguish a single-step exception (due to a previous
+ * hw-breakpoint exception) from a normal one
+ */
+static DEFINE_PER_CPU(struct perf_event *, last_hit_bp);
+
+/*
+ * Flag to denote if the kernel was already single-stepping. Used to
+ * conditionally unset the MSR_SE flag in the single-step exception
+ * following the breakpoint exception.
+ */
+static DEFINE_PER_CPU(bool, is_cpu_singlestep);
+
+/*
+ * Stores the breakpoints currently in use on each breakpoint address
+ * register for each cpus
+ */
+static DEFINE_PER_CPU(struct perf_event *, bp_per_reg);
+
+/*
+ * Install a perf counter breakpoint.
+ *
+ * We seek a free debug address register and use it for this
+ * breakpoint.
+ *
+ * Atomic: we hold the counter->ctx->lock and we only handle variables
+ * and registers local to this cpu.
+ */
+int arch_install_hw_breakpoint(struct perf_event *bp)
+{
+ struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+ struct perf_event **slot = &__get_cpu_var(bp_per_reg);
+
+ if (!*slot)
+ *slot = bp;
+ else {
+ WARN_ONCE(1, "Can't find any breakpoint slot");
+ return -EBUSY;
+ }
+
+ set_dabr(info->address | info->type | DABR_TRANSLATION);
+ return 0;
+}
+
+/*
+ * Uninstall the breakpoint contained in the given counter.
+ *
+ * First we search the debug address register it uses and then we disable
+ * it.
+ *
+ * Atomic: we hold the counter->ctx->lock and we only handle variables
+ * and registers local to this cpu.
+ */
+void arch_uninstall_hw_breakpoint(struct perf_event *bp)
+{
+ struct perf_event **slot = &__get_cpu_var(bp_per_reg);
+
+ if (*slot == bp)
+ *slot = NULL;
+ else {
+ WARN_ONCE(1, "Can't find the breakpoint slot");
+ return;
+ }
+ set_dabr(0);
+}
+
+/*
+ * Validate the arch-specific HW Breakpoint register settings
+ */
+int arch_validate_hwbkpt_settings(struct perf_event *bp,
+ struct task_struct *tsk)
+{
+ int is_kernel, ret = -EINVAL;
+ struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+ if (!bp)
+ return ret;
+
+ switch (bp->attr.bp_type) {
+ case HW_BREAKPOINT_R:
+ info->type = DABR_DATA_READ;
+ break;
+ case HW_BREAKPOINT_W:
+ info->type = DABR_DATA_WRITE;
+ break;
+ case HW_BREAKPOINT_R | HW_BREAKPOINT_W:
+ info->type = (DABR_DATA_READ | DABR_DATA_WRITE);
+ break;
+ default:
+ return ret;
+ }
+ /* TODO: Check for a valid triggered function */
+ /* if (!bp->triggered)
+ return -EINVAL; */
+
+ is_kernel = is_kernel_addr(bp->attr.bp_addr);
+ if ((tsk && is_kernel) || (!tsk && !is_kernel))
+ return -EINVAL;
+
+ info->address = bp->attr.bp_addr;
+ info->len = bp->attr.bp_len;
+
+ /*
+ * Since breakpoint length can be a maximum of HW_BREAKPOINT_LEN(8)
+ * and breakpoint addresses are aligned to nearest double-word
+ * HW_BREAKPOINT_ALIGN by rounding off to the lower address, the
+ * 'symbolsize' should satisfy the check below.
+ */
+ if (info->len >
+ (HW_BREAKPOINT_LEN - (info->address & HW_BREAKPOINT_ALIGN)))
+ return -EINVAL;
+ return 0;
+}
+
+/*
+ * Handle debug exception notifications.
+ */
+int __kprobes hw_breakpoint_handler(struct die_args *args)
+{
+ int rc = NOTIFY_STOP;
+ struct perf_event *bp;
+ struct pt_regs *regs = args->regs;
+ unsigned long dar = regs->dar;
+ int cpu, is_kernel, stepped = 1;
+ struct arch_hw_breakpoint *info;
+
+ /* Disable breakpoints during exception handling */
+ set_dabr(0);
+ cpu = get_cpu();
+ /*
+ * The counter may be concurrently released but that can only
+ * occur from a call_rcu() path. We can then safely fetch
+ * the breakpoint, use its callback, touch its counter
+ * while we are in an rcu_read_lock() path.
+ */
+ rcu_read_lock();
+
+ bp = per_cpu(bp_per_reg, cpu);
+ if (!bp)
+ goto out;
+ info = counter_arch_bp(bp);
+ is_kernel = is_kernel_addr(bp->attr.bp_addr);
+
+ /*
+ * Verify if dar lies within the address range occupied by the symbol
+ * being watched to filter extraneous exceptions.
+ */
+ if (!((bp->attr.bp_addr <= dar) &&
+ (dar <= (bp->attr.bp_addr + bp->attr.bp_len))))
+ /*
+ * This exception is triggered not because of a memory access on
+ * the monitored variable but in the double-word address range
+ * in which it is contained. We will consume this exception,
+ * considering it as 'noise'.
+ */
+ goto out;
+
+ /*
+ * Return early after invoking user-callback function without restoring
+ * DABR if the breakpoint is from ptrace which always operates in
+ * one-shot mode
+ */
+ if (bp->overflow_handler == ptrace_triggered) {
+ (bp->overflow_handler)(bp, 0, NULL, regs);
+ rc = NOTIFY_DONE;
+ goto out;
+ }
+
+ /*
+ * Do not emulate user-space instructions from kernel-space,
+ * instead single-step them.
+ */
+ if (!is_kernel) {
+ current->thread.last_hit_ubp = bp;
+ goto out;
+ }
+
+ /*
+ * Emulating single-step over causative instruction if already
+ * in MSR_SE mode will harm other users of kernel single-stepping
+ * (like an in-kernel debugger), single-step over them.
+ */
+
+ if (regs->msr & MSR_SE) {
+ per_cpu(is_cpu_singlestep, cpu) = true;
+ per_cpu(last_hit_bp, cpu) = bp;
+ goto out;
+ }
+
+ stepped = emulate_step(regs, regs->nip);
+ /* emulate_step() could not execute it, single-step them */
+ if (stepped == 0) {
+ regs->msr |= MSR_SE;
+ if (is_kernel)
+ per_cpu(last_hit_bp, cpu) = bp;
+ else
+ current->thread.last_hit_ubp = bp;
+ per_cpu(last_hit_bp, cpu) = bp;
+ goto out;
+ }
+ /*
+ * As a policy, the callback is invoked in a 'trigger-after-execute'
+ * fashion
+ */
+ (bp->overflow_handler)(bp, 0, NULL, regs);
+ set_dabr(info->address | info->type | DABR_TRANSLATION);
+ per_cpu(is_cpu_singlestep, cpu) = false;
+out:
+ rcu_read_unlock();
+ put_cpu();
+ return rc;
+}
+
+/*
+ * Handle single-step exceptions following a DABR hit.
+ */
+int __kprobes single_step_dabr_instruction(struct die_args *args)
+{
+ struct pt_regs *regs = args->regs;
+ int cpu = get_cpu();
+ int ret = NOTIFY_DONE;
+ siginfo_t info;
+ struct perf_event *bp = NULL, *kernel_bp, *user_bp;
+ struct arch_hw_breakpoint *bp_info;
+
+ /*
+ * Identify the cause of single-stepping and find the corresponding
+ * breakpoint structure
+ */
+ kernel_bp = per_cpu(last_hit_bp, cpu);
+ user_bp = current->thread.last_hit_ubp;
+ if (kernel_bp) {
+ bp = kernel_bp;
+ per_cpu(last_hit_bp, cpu) = NULL;
+ } else if (user_bp) {
+ bp = user_bp;
+ current->thread.last_hit_ubp = NULL;
+ }
+
+ /*
+ * Check if we are single-stepping as a result of a
+ * previous HW Breakpoint exception
+ */
+ if (!bp)
+ goto out;
+
+ bp_info = counter_arch_bp(bp);
+
+ /*
+ * We shall invoke the user-defined callback function in the single
+ * stepping handler to confirm to 'trigger-after-execute' semantics
+ */
+ (bp->overflow_handler)(bp, 0, NULL, regs);
+
+ if (!(per_cpu(is_cpu_singlestep, cpu) ||
+ test_thread_flag(TIF_SINGLESTEP)))
+ regs->msr &= ~MSR_SE;
+
+ /* Deliver signal to user-space */
+ if (!is_kernel_addr(bp->attr.bp_addr)) {
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_HWBKPT;
+ info.si_addr = (void __user *)bp_info->address;
+ force_sig_info(SIGTRAP, &info, current);
+ }
+
+ set_dabr(bp_info->address | bp_info->type | DABR_TRANSLATION);
+ /*
+ * The kernel was in single-step mode before hw-breakpoint
+ * exception, allow them to process the single-step exception further.
+ */
+ if (per_cpu(is_cpu_singlestep, cpu)) {
+ per_cpu(is_cpu_singlestep, cpu) = false;
+ ret = NOTIFY_DONE;
+ } else
+ ret = NOTIFY_STOP;
+out:
+ put_cpu();
+ return ret;
+}
+
+/*
+ * Handle debug exception notifications.
+ */
+int __kprobes hw_breakpoint_exceptions_notify(
+ struct notifier_block *unused, unsigned long val, void *data)
+{
+ int ret = NOTIFY_DONE;
+
+ switch (val) {
+ case DIE_DABR_MATCH:
+ ret = hw_breakpoint_handler(data);
+ break;
+ case DIE_SSTEP:
+ ret = single_step_dabr_instruction(data);
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Release the user breakpoints used by ptrace
+ */
+void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
+{
+ struct thread_struct *t = &tsk->thread;
+
+ unregister_hw_breakpoint(t->ptrace_bps[0]);
+ t->ptrace_bps[0] = NULL;
+}
+
+void hw_breakpoint_pmu_read(struct perf_event *bp)
+{
+ /* TODO */
+}
+
+void hw_breakpoint_pmu_unthrottle(struct perf_event *bp)
+{
+ /* TODO */
+}
+
+
Index: linux-2.6-tip.new_ppc64_perf/arch/powerpc/Kconfig
===================================================================
--- linux-2.6-tip.new_ppc64_perf.orig/arch/powerpc/Kconfig
+++ linux-2.6-tip.new_ppc64_perf/arch/powerpc/Kconfig
@@ -130,6 +130,7 @@ config PPC
select HAVE_SYSCALL_WRAPPERS if PPC64
select GENERIC_ATOMIC64 if PPC32
select HAVE_PERF_EVENTS
+ select HAVE_HW_BREAKPOINT if PPC64
config EARLY_PRINTK
bool
Index: linux-2.6-tip.new_ppc64_perf/arch/powerpc/kernel/Makefile
===================================================================
--- linux-2.6-tip.new_ppc64_perf.orig/arch/powerpc/kernel/Makefile
+++ linux-2.6-tip.new_ppc64_perf/arch/powerpc/kernel/Makefile
@@ -33,7 +33,7 @@ obj-y := cputable.o ptrace.o syscalls
obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \
signal_64.o ptrace32.o \
- paca.o nvram_64.o firmware.o
+ paca.o nvram_64.o firmware.o hw_breakpoint.o
obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_ppc970.o cpu_setup_pa6t.o
obj64-$(CONFIG_RELOCATABLE) += reloc_64.o
obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o
Index: linux-2.6-tip.new_ppc64_perf/arch/powerpc/include/asm/reg.h
===================================================================
--- linux-2.6-tip.new_ppc64_perf.orig/arch/powerpc/include/asm/reg.h
+++ linux-2.6-tip.new_ppc64_perf/arch/powerpc/include/asm/reg.h
@@ -180,6 +180,7 @@
#define CTRL_TE 0x00c00000 /* thread enable */
#define CTRL_RUNLATCH 0x1
#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
+#define HBP_NUM 1 /* Number of physical HW breakpoint registers */
#define DABR_TRANSLATION (1UL << 2)
#define DABR_DATA_WRITE (1UL << 1)
#define DABR_DATA_READ (1UL << 0)
Index: linux-2.6-tip.new_ppc64_perf/arch/powerpc/mm/fault.c
===================================================================
--- linux-2.6-tip.new_ppc64_perf.orig/arch/powerpc/mm/fault.c
+++ linux-2.6-tip.new_ppc64_perf/arch/powerpc/mm/fault.c
@@ -137,6 +137,12 @@ int __kprobes do_page_fault(struct pt_re
error_code &= 0x48200000;
else
is_write = error_code & DSISR_ISSTORE;
+
+ if (error_code & DSISR_DABRMATCH) {
+ /* DABR match */
+ do_dabr(regs, address, error_code);
+ return 0;
+ }
#else
is_write = error_code & ESR_DST;
#endif /* CONFIG_4xx || CONFIG_BOOKE */
@@ -151,14 +157,6 @@ int __kprobes do_page_fault(struct pt_re
if (!user_mode(regs) && (address >= TASK_SIZE))
return SIGSEGV;
-#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
- if (error_code & DSISR_DABRMATCH) {
- /* DABR match */
- do_dabr(regs, address, error_code);
- return 0;
- }
-#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
-
if (in_atomic() || mm == NULL) {
if (!user_mode(regs))
return SIGSEGV;
Index: linux-2.6-tip.new_ppc64_perf/arch/powerpc/include/asm/processor.h
===================================================================
--- linux-2.6-tip.new_ppc64_perf.orig/arch/powerpc/include/asm/processor.h
+++ linux-2.6-tip.new_ppc64_perf/arch/powerpc/include/asm/processor.h
@@ -177,6 +177,12 @@ struct thread_struct {
#ifdef CONFIG_PPC64
unsigned long start_tb; /* Start purr when proc switched in */
unsigned long accum_tb; /* Total accumilated purr for process */
+ struct perf_event *ptrace_bps[HBP_NUM];
+ /*
+ * Point to the hw-breakpoint last. Helps safe pre-emption and
+ * hw-breakpoint re-enablement.
+ */
+ struct perf_event *last_hit_ubp;
#endif
unsigned long dabr; /* Data address breakpoint register */
#ifdef CONFIG_ALTIVEC
Index: linux-2.6-tip.new_ppc64_perf/arch/powerpc/kernel/ptrace.c
===================================================================
--- linux-2.6-tip.new_ppc64_perf.orig/arch/powerpc/kernel/ptrace.c
+++ linux-2.6-tip.new_ppc64_perf/arch/powerpc/kernel/ptrace.c
@@ -32,6 +32,8 @@
#ifdef CONFIG_PPC32
#include <linux/module.h>
#endif
+#include <linux/hw_breakpoint.h>
+#include <linux/perf_event.h>
#include <asm/uaccess.h>
#include <asm/page.h>
@@ -755,9 +757,32 @@ void user_disable_single_step(struct tas
clear_tsk_thread_flag(task, TIF_SINGLESTEP);
}
+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
+ */
+ attr = bp->attr;
+ attr.disabled = true;
+ modify_user_hw_breakpoint(bp, &attr);
+}
+
int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
unsigned long data)
{
+#ifdef CONFIG_PPC64
+ int ret;
+ struct thread_struct *thread = &(task->thread);
+ struct perf_event *bp;
+ struct perf_event_attr attr;
+#endif /* CONFIG_PPC64 */
+
/* For ppc64 we support one DABR and no IABR's at the moment (ppc64).
* For embedded processors we support one DAC and no IAC's at the
* moment.
@@ -786,6 +811,58 @@ int ptrace_set_debugreg(struct task_stru
/* Ensure breakpoint translation bit is set */
if (data && !(data & DABR_TRANSLATION))
return -EIO;
+#ifdef CONFIG_PPC64
+ bp = thread->ptrace_bps[0];
+ if (data == 0) {
+ if (bp) {
+ unregister_hw_breakpoint(bp);
+ thread->ptrace_bps[0] = NULL;
+ }
+ return 0;
+ }
+ if (bp) {
+ attr = bp->attr;
+ attr.bp_addr = data & ~HW_BREAKPOINT_ALIGN;
+
+ switch (data & (DABR_DATA_WRITE | DABR_DATA_READ)) {
+ case DABR_DATA_READ:
+ attr.bp_type = HW_BREAKPOINT_R;
+ break;
+ case DABR_DATA_WRITE:
+ attr.bp_type = HW_BREAKPOINT_W;
+ break;
+ case (DABR_DATA_WRITE | DABR_DATA_READ):
+ attr.bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
+ break;
+ }
+ ret = modify_user_hw_breakpoint(bp, &attr);
+ if (ret)
+ return ret;
+ thread->ptrace_bps[0] = bp;
+ thread->dabr = data;
+ return 0;
+ }
+
+ /* Create a new breakpoint request if one doesn't exist already */
+ hw_breakpoint_init(&attr);
+ attr.bp_addr = data & ~HW_BREAKPOINT_ALIGN;
+ switch (data & (DABR_DATA_WRITE | DABR_DATA_READ)) {
+ case DABR_DATA_READ:
+ attr.bp_type = HW_BREAKPOINT_R;
+ break;
+ case DABR_DATA_WRITE:
+ attr.bp_type = HW_BREAKPOINT_W;
+ break;
+ case (DABR_DATA_WRITE | DABR_DATA_READ):
+ attr.bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
+ break;
+ }
+ thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr,
+ ptrace_triggered, task);
+ if (IS_ERR(bp))
+ return PTR_ERR(bp);
+
+#endif /* CONFIG_PPC64 */
/* Move contents to the DABR register */
task->thread.dabr = data;
Index: linux-2.6-tip.new_ppc64_perf/arch/powerpc/kernel/process.c
===================================================================
--- linux-2.6-tip.new_ppc64_perf.orig/arch/powerpc/kernel/process.c
+++ linux-2.6-tip.new_ppc64_perf/arch/powerpc/kernel/process.c
@@ -48,6 +48,7 @@
#include <asm/machdep.h>
#include <asm/time.h>
#include <asm/syscalls.h>
+#include <asm/hw_breakpoint.h>
#ifdef CONFIG_PPC64
#include <asm/firmware.h>
#endif
@@ -376,8 +377,11 @@ struct task_struct *__switch_to(struct t
if (new->thread.dabr)
set_dabr(new->thread.dabr);
#else
+/* For PPC64, we use the hw-breakpoint interfaces that would schedule DABR */
+#ifndef CONFIG_PPC64
if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
set_dabr(new->thread.dabr);
+#endif /* CONFIG_PPC64 */
#endif
@@ -564,6 +568,7 @@ void flush_thread(void)
else
set_ti_thread_flag(t, TIF_32BIT);
}
+ flush_ptrace_hw_breakpoint(current);
#endif
discard_lazy_cpu_state();
^ permalink raw reply
* [Patch 0/1] PPC64-HWBKPT: Hardware Breakpoint interfaces - ver XII
From: K.Prasad @ 2010-01-21 8:46 UTC (permalink / raw)
To: linuxppc-dev, David Gibson, Roland McGrath
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, Alan Stern, paulus
Hi All,
Please find version XII of the PPC64 implementation of the
hardware breakpoint interfaces.
Changelog - ver XII
--------------------
(Version XI: linuxppc-dev ref: 20100119091234.GA9971@in.ibm.com)
- Unset MSR_SE only if kernel was not previously in single-step mode.
- Pre-emption is now enabled before returning from the hw-breakpoint exception
handler.
- Variables to track the source of single-step exception (breakpoint from kernel,
user-space vs single-stepping due to other requests) are added.
- Extraneous hw-breakpoint exceptions (due to memory accesses lying outside
monitored symbol length) is now done for both kernel and user-space
(previously only user-space).
- single_step_dabr_instruction() now returns NOTIFY_DONE if kernel was in
single-step mode even before the hw-breakpoint. This enables other users of
single-step mode to be notified of the exception.
- User-space instructions are not emulated from kernel-space, they are instead
single-stepped.
Looking forward for your comments.
Thanks,
K.Prasad
Changelog - ver XI
------------------
(Version X: linuxppc-dev ref: 20091211160144.GA23156@in.ibm.com)
- Conditionally unset MSR_SE in the single-step handler
- Added comments to explain the duration and need for pre-emption
disable following hw-breakpoint exception.
Changelog - ver X
------------------
- Re-write the PPC64 patches for the new implementation of hw-breakpoints that
uses the perf-layer.
- Rebased to commit 7622fc234190a37d4e9fe3ed944a2b61a63fca03 of -tip.
Changelog - ver IX
-------------------
- Invocation of user-defined callback will be 'trigger-after-execute' (except
for ptrace).
- Creation of a new global per-CPU breakpoint structure to help invocation of
user-defined callback from single-step handler.
(Changes made now)
- Validation before registration will fail only if the address does not match
the kernel symbol's (if specified) resolved address
(through kallsyms_lookup_name()).
- 'symbolsize' value is expected to within the range contained by the symbol's
starting address and the end of a double-word boundary (8 Bytes).
- PPC64's arch-dependant code is now aware of 'cpumask' in 'struct hw_breakpoint'
and can accomodate requests for a subset of CPUs in the system.
- Introduced arch_disable_hw_breakpoint() required for
<enable><disable>_hw_breakpoint() APIs.
Changelog - ver VIII
-------------------
- Reverting changes to allow one-shot breakpoints only for ptrace requests.
- Minor changes in sanity checking in arch_validate_hwbkpt_settings().
- put_cpu_no_resched() is no longer available. Converted to put_cpu().
Changelog - ver VII
-------------------
- Allow the one-shot behaviour for exception handlers to be defined by the user.
A new 'is_one_shot' flag is added to 'struct arch_hw_breakpoint'.
Changelog - ver VI
------------------
The task of identifying 'genuine' breakpoint exceptions from those caused by
'out-of-range' accesses turned out to be more tricky than originally thought.
Some changes to this effect were made in version IV of this patchset, but they
were not sufficient for user-space. Basically the breakpoint address received
through ptrace is always aligned to 8-bytes since ptrace receives an encoded
'data' (consisting of address | translation_enable | bkpt_type), and the size of
the symbol is not known. However for kernel-space addresses, the symbol-size can
be determined using kallsyms_lookup_size_offset() and this is used to check if
DAR (in the exception context) is
'bkpt_address <= DAR <= (bkpt_address + symbol_size)', failing which we conclude
it as a stray exception.
The following changes are made to enable check:
- Addition of a symbolsize field in 'struct arch_hw_breakpoint' field.
- Store the size of the 'watched' kernel symbol into 'symbolsize' field in
arch_store_info(0 routine.
- Verify if the above described condition is true when is_one_shot is FALSE in
hw_breakpoint_handler().
Changelog - ver V
------------------
- Breakpoint requests from ptrace (for user-space) are designed to be one-shot
in PPC64. The patch contains changes to retain this behaviour by returning early
in hw_breakpoint_handler() [without re-initialising DABR] and unregistering the
user-space request in ptrace_triggered(). It is safe to make a
unregister_user_hw_breakpoint() call from the breakpoint exception context
[through ptrace_triggered()] without giving rise to circular locking-dependancy.
This is because there can be no kernel code running on the CPU (which received
the exception) with the same spinlock held.
- Minor change in 'type' member of 'struct arch_hw_breakpoint' from u8 to 'int'.
Changelog - ver IV
------------------
- While DABR register requires double-word (8 bytes) aligned addresses, i.e.
the breakpoint is active over a range of 8 bytes, PPC64 allows byte-level
addressability. This may lead to stray exceptions which have to be ignored in
hw_breakpoint_handler(), when DAR != (Breakpoint request address). However DABR
will be populated with the requested breakpoint address aligned to the previous
double-word address. The code is now modified to store user-requested address
in 'bp->info.address' but update the DABR with a double-word aligned address.
- Please note that the Data Breakpoint facility in Xmon is broken as of 2.6.29
and the same has not been integrated into this facility as described in Ver I.
Changelog - ver III
------------------
- Patches are based on commit 08f16e060bf54bdc34f800ed8b5362cdeda75d8b of -tip
tree.
- The declarations in arch/powerpc/include/asm/hw_breakpoint.h are done only if
CONFIG_PPC64 is defined. This eliminates the need to conditionally include this
header file.
- load_debug_registers() is done in start_secondary() i.e. during CPU
initialisation.
- arch_check_va_<> routines in hw_breakpoint.c are now replaced with a much
simpler is_kernel_addr() check in arch_validate_hwbkpt_settings()
- Return code of hw_breakpoint_handler() when triggered due to Lazy debug
register switching is now changed to NOTIFY_STOP.
- The ptrace code no longer sets the TIF_DEBUG task flag as it is proposed to
be done in register_user_hw_breakpoint() routine.
- hw_breakpoint_handler() is now modified to use hbp_kernel_pos value to
determine if the trigger was a user/kernel space address. The DAR register
value is checked with the address stored in 'struct hw_breakpoint' to avoid
handling of exceptions that belong to kprobe/Xmon.
Changelog - ver II
------------------
- Split the monolithic patch into six logical patches
- Changed the signature of arch_check_va_in_<user><kernel>space functions. They
are now marked static.
- HB_NUM is now called as HBP_NUM (to preserve a consistent short-name
convention)
- Introduced hw_breakpoint_disable() and changes to kexec code to disable
breakpoints before a reboot.
- Minor changes in ptrace code to use macro-defined constants instead of
numbers.
- Introduced a new constant definition INSTRUCTION_LEN in reg.h
^ permalink raw reply
* Re: [PATCH 2/2] powerpc: implement arch_scale_smt_power for Power7
From: Peter Zijlstra @ 2010-01-21 8:27 UTC (permalink / raw)
To: Joel Schopp
Cc: ego, Andreas Herrmann, linux-kernel, Ingo Molnar, linuxppc-dev
In-Reply-To: <4B578731.2060709@austin.ibm.com>
On Wed, 2010-01-20 at 16:44 -0600, Joel Schopp wrote:
>
> Care to take Gautham's bugfix patch (patch 1/2) now, since it just fixes
> a bug? You'll need it if you ever try to make the x86 broken version work.
Sure, I'll take that, thanks!
^ permalink raw reply
* Re: How to trun off udbg0 during bootup?
From: 景文林 @ 2010-01-21 6:58 UTC (permalink / raw)
To: SHAN Gavin; +Cc: linuxppc-dev
In-Reply-To: <6A5F574C5A990242B0541891CF955C0D01D1EDBD@CNSHGSMBS05.ad4.ad.alcatel.com>
[-- Attachment #1: Type: text/plain, Size: 804 bytes --]
2010/1/21 SHAN Gavin <Gavin.Shan@alcatel-lucent.com>
>
>
> Hi,
>
> I `m working on a freescale-MPC8379eRDB like board.And I want to trun off
> kernel message during bootup.
>
> I tried to modify "console = XXX" argument in uboot but it did not
> work(It
> works on ARM). Kernel always print:
>
> "console [udbg0] enabled" or "console handover: boot [*udbg0*] -> real
> [ttyS1]"
>
> Does anybody know how can I turn off this udbg0?
>
> You may check arch/powerpc/kernel/udbg.c and disable registering the early
> debug console driver. Then you can not see the output before the message
> line like "-> real [ttyS1]"
>
> Good luck,
> Gavin
>
> I assigned 1 to "static int early_console_initialized". The driver did
not register early debug console.
It`s worked.
Thank you!
Regards
jing wenlin
[-- Attachment #2: Type: text/html, Size: 1337 bytes --]
^ permalink raw reply
* [PATCH -tip tracing/kprobes v3] Powerpc port of the kprobe-based event tracer
From: Mahesh Salgaonkar @ 2010-01-21 6:12 UTC (permalink / raw)
To: linux-kernel
Cc: Michael Neuling, Mahesh Salgaonkar, linuxppc-dev, systemtap,
Ingo Molnar, Masami Hiramatsu
In-Reply-To: <20100121060941.602302318@mars.in.ibm.com>
This patch ports the kprobe-based event tracer to powerpc. This patch
is based on x86 port. This brings powerpc on par with x86.
ChangeLog:
v2:
- Removed regs_get_argument_nth() API as function argument access syntax
is dropped from kprobe-tracer. Please refer to mails below on Linux PPC
mailing list:
http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-January/079331.html
http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-January/079332.html
v3:
- The registers gpr[0]...gpr[31] will now be represented as gpr0...gpr31
- The pt_regs structure members orig_gpr3 and result will not be exposed
as they are not actual registers.
- Rebased to commit 605a39d5a0f4856214b37db954f553fba28bb616 of -tip
This patch is dependent on:
http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-January/079331.html
Port the following API's to ppc for accessing registers and stack entries
from pt_regs.
- regs_query_register_offset(const char *name)
Query the offset of "name" register.
- regs_query_register_name(unsigned int offset)
Query the name of register by its offset.
- regs_get_register(struct pt_regs *regs, unsigned int offset)
Get the value of a register by its offset.
- regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
Check the address is in the kernel stack.
- regs_get_kernel_stack_nth(struct pt_regs *reg, unsigned int nth)
Get Nth entry of the kernel stack. (N >= 0)
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Acked-by: Masami Hiramatsu <mhiramat@redhat.com>
---
arch/powerpc/include/asm/ptrace.h | 61 ++++++++++++++++++++++
arch/powerpc/kernel/ptrace.c | 103 +++++++++++++++++++++++++++++++++++++
kernel/trace/Kconfig | 2 -
3 files changed, 165 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index cbd759e..f4a78c5 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -83,6 +83,7 @@ struct pt_regs {
#define instruction_pointer(regs) ((regs)->nip)
#define user_stack_pointer(regs) ((regs)->gpr[1])
+#define kernel_stack_pointer(regs) ((regs)->gpr[1])
#define regs_return_value(regs) ((regs)->gpr[3])
#ifdef CONFIG_SMP
@@ -131,6 +132,66 @@ do { \
} while (0)
#endif /* __powerpc64__ */
+/* Query offset/name of register from its name/offset */
+#include <linux/stddef.h>
+#include <linux/thread_info.h>
+extern int regs_query_register_offset(const char *name);
+extern const char *regs_query_register_name(unsigned int offset);
+#define MAX_REG_OFFSET (offsetof(struct pt_regs, dsisr))
+
+/**
+ * regs_get_register() - get register value from its offset
+ * @regs: pt_regs from which register value is gotten
+ * @offset: offset number of the register.
+ *
+ * regs_get_register returns the value of a register whose offset from @regs.
+ * The @offset is the offset of the register in struct pt_regs.
+ * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
+ */
+static inline unsigned long regs_get_register(struct pt_regs *regs,
+ unsigned int offset)
+{
+ if (unlikely(offset > MAX_REG_OFFSET))
+ return 0;
+ return *(unsigned long *)((unsigned long)regs + offset);
+}
+
+/**
+ * regs_within_kernel_stack() - check the address in the stack
+ * @regs: pt_regs which contains kernel stack pointer.
+ * @addr: address which is checked.
+ *
+ * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
+ * If @addr is within the kernel stack, it returns true. If not, returns false.
+ */
+
+static inline bool regs_within_kernel_stack(struct pt_regs *regs,
+ unsigned long addr)
+{
+ return ((addr & ~(THREAD_SIZE - 1)) ==
+ (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
+}
+
+/**
+ * regs_get_kernel_stack_nth() - get Nth entry of the stack
+ * @regs: pt_regs which contains kernel stack pointer.
+ * @n: stack entry number.
+ *
+ * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
+ * is specified by @regs. If the @n th entry is NOT in the kernel stack,
+ * this returns 0.
+ */
+static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
+ unsigned int n)
+{
+ unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
+ addr += n;
+ if (regs_within_kernel_stack(regs, (unsigned long)addr))
+ return *addr;
+ else
+ return 0;
+}
+
/*
* These are defined as per linux/ptrace.h, which see.
*/
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index ef14988..56651c2 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -39,6 +39,109 @@
#include <asm/system.h>
/*
+ * The parameter save area on the stack is used to store arguments being passed
+ * to callee function and is located at fixed offset from stack pointer.
+ */
+#ifdef CONFIG_PPC32
+#define PARAMETER_SAVE_AREA_OFFSET 24 /* bytes */
+#else /* CONFIG_PPC32 */
+#define PARAMETER_SAVE_AREA_OFFSET 48 /* bytes */
+#endif
+
+struct pt_regs_offset {
+ const char *name;
+ int offset;
+};
+
+#define STR(s) #s /* convert to string */
+#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
+#define GPR_OFFSET_NAME(num) \
+ {.name = STR(gpr##num), .offset = offsetof(struct pt_regs, gpr[num])}
+#define REG_OFFSET_END {.name = NULL, .offset = 0}
+
+static const struct pt_regs_offset regoffset_table[] = {
+ GPR_OFFSET_NAME(0),
+ GPR_OFFSET_NAME(1),
+ GPR_OFFSET_NAME(2),
+ GPR_OFFSET_NAME(3),
+ GPR_OFFSET_NAME(4),
+ GPR_OFFSET_NAME(5),
+ GPR_OFFSET_NAME(6),
+ GPR_OFFSET_NAME(7),
+ GPR_OFFSET_NAME(8),
+ GPR_OFFSET_NAME(9),
+ GPR_OFFSET_NAME(10),
+ GPR_OFFSET_NAME(11),
+ GPR_OFFSET_NAME(12),
+ GPR_OFFSET_NAME(13),
+ GPR_OFFSET_NAME(14),
+ GPR_OFFSET_NAME(15),
+ GPR_OFFSET_NAME(16),
+ GPR_OFFSET_NAME(17),
+ GPR_OFFSET_NAME(18),
+ GPR_OFFSET_NAME(19),
+ GPR_OFFSET_NAME(20),
+ GPR_OFFSET_NAME(21),
+ GPR_OFFSET_NAME(22),
+ GPR_OFFSET_NAME(23),
+ GPR_OFFSET_NAME(24),
+ GPR_OFFSET_NAME(25),
+ GPR_OFFSET_NAME(26),
+ GPR_OFFSET_NAME(27),
+ GPR_OFFSET_NAME(28),
+ GPR_OFFSET_NAME(29),
+ GPR_OFFSET_NAME(30),
+ GPR_OFFSET_NAME(31),
+ REG_OFFSET_NAME(nip),
+ REG_OFFSET_NAME(msr),
+ REG_OFFSET_NAME(ctr),
+ REG_OFFSET_NAME(link),
+ REG_OFFSET_NAME(xer),
+ REG_OFFSET_NAME(ccr),
+#ifdef CONFIG_PPC64
+ REG_OFFSET_NAME(softe),
+#else
+ REG_OFFSET_NAME(mq),
+#endif
+ REG_OFFSET_NAME(trap),
+ REG_OFFSET_NAME(dar),
+ REG_OFFSET_NAME(dsisr),
+ REG_OFFSET_END,
+};
+
+/**
+ * regs_query_register_offset() - query register offset from its name
+ * @name: the name of a register
+ *
+ * regs_query_register_offset() returns the offset of a register in struct
+ * pt_regs from its name. If the name is invalid, this returns -EINVAL;
+ */
+int regs_query_register_offset(const char *name)
+{
+ const struct pt_regs_offset *roff;
+ for (roff = regoffset_table; roff->name != NULL; roff++)
+ if (!strcmp(roff->name, name))
+ return roff->offset;
+ return -EINVAL;
+}
+
+/**
+ * regs_query_register_name() - query register name from its offset
+ * @offset: the offset of a register in struct pt_regs.
+ *
+ * regs_query_register_name() returns the name of a register from its
+ * offset in struct pt_regs. If the @offset is invalid, this returns NULL;
+ */
+const char *regs_query_register_name(unsigned int offset)
+{
+ const struct pt_regs_offset *roff;
+ for (roff = regoffset_table; roff->name != NULL; roff++)
+ if (roff->offset == offset)
+ return roff->name;
+ return NULL;
+}
+
+/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
*/
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 6c22d8a..4d95966 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -451,7 +451,7 @@ config BLK_DEV_IO_TRACE
config KPROBE_EVENT
depends on KPROBES
- depends on X86
+ depends on X86 || PPC
bool "Enable kprobes-based dynamic events"
select TRACING
default y
^ permalink raw reply related
* RE: How to trun off udbg0 during bootup?
From: SHAN Gavin @ 2010-01-21 3:56 UTC (permalink / raw)
To: ???, linuxppc-dev
In-Reply-To: <b90a809a1001201702y7d42eb60v43f24cb1043a89fa@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 581 bytes --]
Hi,
I `m working on a freescale-MPC8379eRDB like board.And I want to trun off
kernel message during bootup.
I tried to modify "console = XXX" argument in uboot but it did not work(It
works on ARM). Kernel always print:
"console [udbg0] enabled" or "console handover: boot [*udbg0*] -> real
[ttyS1]"
Does anybody know how can I turn off this udbg0?
You may check arch/powerpc/kernel/udbg.c and disable registering the early
debug console driver. Then you can not see the output before the message
line like "-> real [ttyS1]"
Good luck,
Gavin
[-- Attachment #2: Type: text/html, Size: 1137 bytes --]
^ 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