[Patch 0/5] PPC64-HWBKPT: Hardware Breakpoint interfaces - ver XXIV
Hi Paul, Please find a new set of patches with changes as described below. The patches have been tested for kernel- and user-mode breakpoints (after applying the two patches you sent, refer message-id: 20100603004758.ga19...@brick.ozlabs.ibm.com and message-id: 20100615015459.ga30...@drongo) and are found to work fine! Changelog - ver XXIV (Version XXII: 20100609102446.ga20...@in.ibm.com) - A lockdep issue seen due to invocation of unregister_hw_breakpoint() in exception context is now fixed (perf_event_disable() is used instead). - Fixed improper handling of extraneous exceptions (through clearing of extraneous exception flag and preventing the invocation of callback). Kindly let me know if you have any further comments. Thanks, K.Prasad Changelog - ver XXIII (Version XXII: 20100528063924.ga8...@in.ibm.com) - Detection of extraneous breakpoint exceptions is now done using a boolean flag in 'struct arch_hw_breakpoint'. - A dangling put_cpu() (remnant from previous patch versions) in arch_unregister_hw_breakpoint() is now removed. Changelog - ver XXII (Version XXI: linuxppc-dev ref:20100525091314.ga29...@in.ibm.com) - Extraneous breakpoint exceptions are now properly handled; causative instruction will be single-stepped and debug register values restored. - Restoration of breakpoints during signal handling through thread_change_pc() had defects which are now fixed. - Breakpoints are flushed through flush_ptrace_hw_breakpoint() call in both flush_thread() and prepare_to_copy() functions. 'ptrace_bps[]' and 'last_hit_ubp' members are now promptly cleaned-up. - Single-step exception is now conditionally emulated upon hitting alignment_exception. - Rebased to commit 31f46717997a83bdf6db0dd04810c0a329eb3148 of linux-2.6 tree. Changelog - ver XXI (Version XX: linuxppc-dev ref:20100524103136.ga8...@in.ibm.com) - Decision to emulate an instruction is now based on whether the causative instruction is in user_mode() or not. - Breakpoints don't have to be cleared during sigreturn. A 'double-hit' on hw_breakpoint_handler() is harmless for non-ptrace instructions. - Minor changes to aid code brevity. Changelog - ver XX (Version XIX: linuxppc-dev ref: 20100524040137.ga20...@in.ibm.com) - Non task-bound breakpoints will only be emulated. Breakpoint will be unregistered with a warning if emulation fails. Changelog - ver XIX (Version XVIII: linuxppc-dev ref: 20100512033055.ga6...@in.ibm.com) - Increased coverage of breakpoints during concurrent alignment_exception and signal handling (which previously had 'blind-spots'). - Support for kernel-thread breakpoints and kernel-space breakpoints inside the context of a user-space process. - Patches re-based to commit f4b87dee923342505e1ddba8d34ce9de33e75050, thereby necessitating minor changes to arch_validate_hwbkpt_settings(). Changelog - ver XVIII (Version XVII: linuxppc-dev ref: 20100414034340.ga6...@in.ibm.com) - Slight code restructuring for brevity and coding-style corrections. - emulate_single_step() now notifies DIE_SSTEP to registered handlers; causes single_step_dabr_instruction() to be invoked after alignment_exception. - hw-breakpoint restoration variables are cleaned-up before unregistration through arch_unregister_hw_breakpoint(). - SIGTRAP is no longer generated for non-ptrace user-space breakpoints. Changelog - ver XVII (Version XVI: linuxppc-dev ref: 20100330095809.ga14...@in.ibm.com) - CONFIG_HAVE_HW_BREAKPOINT is now used to define the scope of the new code (in lieu of CONFIG_PPC_BOOK3S_64). - CONFIG_HAVE_HW_BREAKPOINT is now dependant upon CONFIG_PERF_EVENTS and CONFIG_PPC_BOOK3S_64 (to overcome build failures under certain configs). - Included a target in arch/powerpc/lib/Makefile to build sstep.o when HAVE_HW_BREAKPOINT. - Added a dummy definition for hw_breakpoint_disable() when !HAVE_HW_BREAKPOINT. - Tested builds under defconfigs for ppc64, cell and g5 (found no patch induced failures). Changelog - ver XVI (Version XV: linuxppc-dev ref: 20100323140639.ga21...@in.ibm.com) - Used a new config option CONFIG_PPC_BOOK3S_64 (in lieu of CONFIG_PPC64/CPU_FTR_HAS_DABR) to limit the scope of the new code. - Disabled breakpoints before kexec of the machine using hw_breakpoint_disable(). - Minor optimisation in exception-64s.S to check for data breakpoint exceptions in DSISR finally (after check for other causes) + changes in code comments and representation of DSISR_DABRMATCH constant. - Rebased to commit ae6be51ed01d6c4aaf249a207b4434bc7785853b of linux-2.6. Changelog - ver XV (Version XIV: linuxppc-dev ref: 20100308181232.ga3...@in.ibm.com) - Additional patch to disable interrupts during data breakpoint exception handling. - Moved HBP_NUM definition to cputable.h under a new CPU_FTR
[Patch 1/5] Allow arch-specific cleanup before breakpoint unregistration
Certain architectures (such as PowerPC Book III S) have a need to cleanup data-structures before the breakpoint is unregistered. This patch introduces an arch-specific hook in release_bp_slot() along with a weak definition in the form of a stub funciton. Signed-off-by: K.Prasad pra...@linux.vnet.ibm.com Acked-by: Frederic Weisbecker fweis...@gmail.com --- kernel/hw_breakpoint.c | 12 1 file changed, 12 insertions(+) Index: linux-2.6.ppc64_test/kernel/hw_breakpoint.c === --- linux-2.6.ppc64_test.orig/kernel/hw_breakpoint.c +++ linux-2.6.ppc64_test/kernel/hw_breakpoint.c @@ -242,6 +242,17 @@ toggle_bp_slot(struct perf_event *bp, bo } /* + * Function to perform processor-specific cleanup during unregistration + */ +__weak void arch_unregister_hw_breakpoint(struct perf_event *bp) +{ + /* +* A weak stub function here for those archs that don't define +* it inside arch/.../kernel/hw_breakpoint.c +*/ +} + +/* * Contraints to check before allowing this new breakpoint counter: * * == Non-pinned counter == (Considered as pinned for now) @@ -339,6 +350,7 @@ void release_bp_slot(struct perf_event * { mutex_lock(nr_bp_mutex); + arch_unregister_hw_breakpoint(bp); __release_bp_slot(bp); mutex_unlock(nr_bp_mutex); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[Patch 2/5] PPC64-HWBKPT: Implement hw-breakpoints for PowerPC BookIII S
Implement perf-events based hw-breakpoint interfaces for PowerPC Book III S processors. These interfaces help arbitrate requests from various users and schedules them as appropriate. [Suggestions from Paul Mackerras pau...@samba.org to - emulate_step() all non-task bound breakpoints and single-step only the per-task breakpoints - perform arch-specific cleanup before unregistration through arch_unregister_hw_breakpoint() ] Signed-off-by: K.Prasad pra...@linux.vnet.ibm.com --- arch/powerpc/Kconfig |1 arch/powerpc/include/asm/cputable.h |4 arch/powerpc/include/asm/hw_breakpoint.h | 73 +++ arch/powerpc/include/asm/processor.h |8 arch/powerpc/kernel/Makefile |1 arch/powerpc/kernel/hw_breakpoint.c | 320 +++ arch/powerpc/kernel/machine_kexec_64.c |3 arch/powerpc/kernel/process.c| 14 + arch/powerpc/kernel/ptrace.c | 64 ++ arch/powerpc/lib/Makefile|1 10 files changed, 489 insertions(+) Index: linux-2.6.ppc64_test/arch/powerpc/include/asm/hw_breakpoint.h === --- /dev/null +++ linux-2.6.ppc64_test/arch/powerpc/include/asm/hw_breakpoint.h @@ -0,0 +1,73 @@ +/* + * PowerPC BookIII S hardware breakpoint definitions + * + * 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 2010, IBM Corporation. + * Author: K.Prasad pra...@linux.vnet.ibm.com + * + */ + +#ifndef _PPC_BOOK3S_64_HW_BREAKPOINT_H +#define _PPC_BOOK3S_64_HW_BREAKPOINT_H + +#ifdef __KERNEL__ +#ifdef CONFIG_HAVE_HW_BREAKPOINT + +struct arch_hw_breakpoint { + u8 len; /* length of the target data symbol */ + int type; + unsigned long address; +}; + +#include linux/kdebug.h +#include asm/reg.h +#include asm/system.h + +static inline int hw_breakpoint_slots(int type) +{ + return HBP_NUM; +} +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_bp_generic_fields(int type, int *gen_bp_type); +extern int arch_check_bp_in_kernelspace(struct perf_event *bp); +extern int arch_validate_hwbkpt_settings(struct perf_event *bp); +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); +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 /* CONFIG_HAVE_HW_BREAKPOINT */ +static inline void hw_breakpoint_disable(void) { } +#endif /* CONFIG_HAVE_HW_BREAKPOINT */ +#endif /* __KERNEL__ */ +#endif /* _PPC_BOOK3S_64_HW_BREAKPOINT_H */ Index: linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c === --- /dev/null +++ linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c @@ -0,0 +1,320 @@ +/* + * 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. + * + *
[Patch 3/5] PPC64-HWBKPT: Handle concurrent alignment interrupts
An alignment interrupt may intervene between a DSI/hw-breakpoint exception and the single-step exception. Enable the alignment interrupt (through modifications to emulate_single_step()) to notify the single-step exception handler for proper restoration of hw-breakpoints. [The need to invoke single-step handler after alignment interrupt pointed out by Paul Mackerras pau...@samba.org] Signed-off-by: K.Prasad pra...@linux.vnet.ibm.com --- arch/powerpc/kernel/traps.c |8 +++- 1 file changed, 3 insertions(+), 5 deletions(-) Index: linux-2.6.ppc64_test/arch/powerpc/kernel/traps.c === --- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/traps.c +++ linux-2.6.ppc64_test/arch/powerpc/kernel/traps.c @@ -602,7 +602,7 @@ void RunModeException(struct pt_regs *re void __kprobes single_step_exception(struct pt_regs *regs) { - regs-msr = ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */ + clear_single_step(regs); if (notify_die(DIE_SSTEP, single_step, regs, 5, 5, SIGTRAP) == NOTIFY_STOP) @@ -621,10 +621,8 @@ void __kprobes single_step_exception(str */ static void emulate_single_step(struct pt_regs *regs) { - if (single_stepping(regs)) { - clear_single_step(regs); - _exception(SIGTRAP, regs, TRAP_TRACE, 0); - } + if (single_stepping(regs)) + single_step_exception(regs); } static inline int __parse_fpscr(unsigned long fpscr) ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[Patch 4/5] PPC64-HWBKPT: Enable hw-breakpoints while handling intervening signals
A signal delivered between a hw_breakpoint_handler() and the single_step_dabr_instruction() will not have the breakpoint active during signal handling (since breakpoint will not be restored through single-stepping due to absence of MSR_SE bit on the signal frame). Enable breakpoints before signal delivery. Restore hw-breakpoints if the user-context is altered in the signal handler. [With inputs from Paul Mackerras pau...@samba.org which helped identify a need to restore breakpoints before handling a signal delivered in certain cases] Signed-off-by: K.Prasad pra...@linux.vnet.ibm.com --- arch/powerpc/include/asm/hw_breakpoint.h |3 +++ arch/powerpc/kernel/hw_breakpoint.c | 18 ++ arch/powerpc/kernel/signal.c |3 +++ 3 files changed, 24 insertions(+) Index: linux-2.6.ppc64_test/arch/powerpc/include/asm/hw_breakpoint.h === --- linux-2.6.ppc64_test.orig/arch/powerpc/include/asm/hw_breakpoint.h +++ linux-2.6.ppc64_test/arch/powerpc/include/asm/hw_breakpoint.h @@ -65,9 +65,12 @@ static inline void hw_breakpoint_disable { set_dabr(0); } +extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs); #else /* CONFIG_HAVE_HW_BREAKPOINT */ static inline void hw_breakpoint_disable(void) { } +static inline void thread_change_pc(struct task_struct *tsk, + struct pt_regs *regs) { } #endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* __KERNEL__ */ #endif /* _PPC_BOOK3S_64_HW_BREAKPOINT_H */ Index: linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c === --- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/hw_breakpoint.c +++ linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c @@ -174,6 +174,24 @@ int arch_validate_hwbkpt_settings(struct } /* + * Restores the breakpoint on the debug registers. + * Invoke this function if it is known that the execution context is about to + * change to cause loss of MSR_SE settings. + */ +void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs) +{ + struct arch_hw_breakpoint *info; + + if (likely(!tsk-thread.last_hit_ubp)) + return; + + info = counter_arch_bp(tsk-thread.last_hit_ubp); + regs-msr = ~MSR_SE; + set_dabr(info-address | info-type | DABR_TRANSLATION); + tsk-thread.last_hit_ubp = NULL; +} + +/* * Handle debug exception notifications. */ int __kprobes hw_breakpoint_handler(struct die_args *args) Index: linux-2.6.ppc64_test/arch/powerpc/kernel/signal.c === --- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/signal.c +++ linux-2.6.ppc64_test/arch/powerpc/kernel/signal.c @@ -11,6 +11,7 @@ #include linux/tracehook.h #include linux/signal.h +#include asm/hw_breakpoint.h #include asm/uaccess.h #include asm/unistd.h @@ -149,6 +150,8 @@ static int do_signal_pending(sigset_t *o if (current-thread.dabr) set_dabr(current-thread.dabr); #endif + /* Re-enable the breakpoints for the signal stack */ + thread_change_pc(current, regs); if (is32) { if (ka.sa.sa_flags SA_SIGINFO) ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[Patch 5/5] PPC64-HWBKPT: Discard extraneous interrupt due to accesses outside symbol length
Many a times, the requested breakpoint length can be less than the fixed breakpoint length i.e. 8 bytes supported by PowerPC BookIII S. This could lead to extraneous interrupts resulting in false breakpoint notifications. The patch below detects and discards such interrupts for non-ptrace requests (we don't want to change ptrace behaviour for fear of breaking compatability). [Suggestions from Paul Mackerras pau...@samba.org to add a new flag in 'struct arch_hw_breakpoint' to identify extraneous interrupts] Signed-off-by: K.Prasad pra...@linux.vnet.ibm.com --- arch/powerpc/include/asm/hw_breakpoint.h |1 + arch/powerpc/kernel/hw_breakpoint.c | 23 +-- 2 files changed, 22 insertions(+), 2 deletions(-) Index: linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c === --- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/hw_breakpoint.c +++ linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c @@ -202,6 +202,7 @@ int __kprobes hw_breakpoint_handler(stru struct pt_regs *regs = args-regs; int stepped = 1; struct arch_hw_breakpoint *info; + unsigned long dar = regs-dar; /* Disable breakpoints during exception handling */ set_dabr(0); @@ -232,6 +233,22 @@ int __kprobes hw_breakpoint_handler(stru goto out; } + /* +* 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'. +*/ + info-extraneous_interrupt = true; + } else + info-extraneous_interrupt = false; + /* Do not emulate user-space instructions, instead single-step them */ if (user_mode(regs)) { bp-ctx-task-thread.last_hit_ubp = bp; @@ -255,7 +272,8 @@ int __kprobes hw_breakpoint_handler(stru * As a policy, the callback is invoked in a 'trigger-after-execute' * fashion */ - perf_bp_event(bp, regs); + if (!info-extraneous_interrupt) + perf_bp_event(bp, regs); set_dabr(info-address | info-type | DABR_TRANSLATION); out: @@ -286,7 +304,8 @@ int __kprobes single_step_dabr_instructi * We shall invoke the user-defined callback function in the single * stepping handler to confirm to 'trigger-after-execute' semantics */ - perf_bp_event(bp, regs); + if (!bp_info-extraneous_interrupt) + perf_bp_event(bp, regs); /* * Do not disable MSR_SE if the process was already in Index: linux-2.6.ppc64_test/arch/powerpc/include/asm/hw_breakpoint.h === --- linux-2.6.ppc64_test.orig/arch/powerpc/include/asm/hw_breakpoint.h +++ linux-2.6.ppc64_test/arch/powerpc/include/asm/hw_breakpoint.h @@ -27,6 +27,7 @@ #ifdef CONFIG_HAVE_HW_BREAKPOINT struct arch_hw_breakpoint { + boolextraneous_interrupt; u8 len; /* length of the target data symbol */ int type; unsigned long address; ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [Patch 5/5] PPC64-HWBKPT: Discard extraneous interrupt due to accesses outside symbol length
On Thu, Jun 10, 2010 at 10:40:24PM +1000, Paul Mackerras wrote: On Wed, Jun 09, 2010 at 03:55:59PM +0530, K.Prasad wrote: + 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'. +*/ + info-extraneous_interrupt = true; + } Ummm, don't you need to add else info-extraneous_interrupt = false; here? I don't see anywhere that you ever clear it otherwise. Also, I think you need to do the if (!info-extraneous_interrupt) check around the call to perf_bp_event() later on in hw_breakpoint_handler() as well as around the call in single_step_dabr_instruction(). Paul. True, I've added the check before perf_bp_event() (wherever it was missing before) in the patchset ver XXIV. Thanks, K.Prasad ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [Patch 0/5] PPC64-HWBKPT: Hardware Breakpoint interfaces - ver XXII
On Tue, Jun 15, 2010 at 11:54:59AM +1000, Paul Mackerras wrote: On Fri, Jun 04, 2010 at 12:21:45PM +0530, K.Prasad wrote: Meanwhile I tested the per-cpu breakpoints with the new emulate_step patch (refer linuxppc-dev message-id: 20100602112903.gb30...@brick.ozlabs.ibm.com) and they continue to fail due to emulate_step() failure, in my case, on a lwz r0,0(r28) instruction. You need to pass the instruction word to emulate_step(), not the instruction address. Also you need to have the full GPR set available. The patch below fixes these problems. I'll fold these changes into your patch 2/5. Paul. The breakpoints that used to fail before (due to emulate_step() failure) are now working fine upon applying this patch. Please include this patch along with my 2/5 as indicated by you. Thanks, K.Prasad ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[git pull] Please pull powerpc.git next branch
Hi Linus ! Here's a few powerpc fixes for 2.6.35. The diffstat is sadly bloated by a small defconfig change, I hate that too :-) We'll switch to some better mechanism as soon as the dust as settled on what that mechanism should be, hopefully real soon. Cheers, Ben. The following changes since commit 7e27d6e778cd87b6f2415515d7127eba53fe5d02: Linus Torvalds (1): Linux 2.6.35-rc3 are available in the git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git merge Alastair Bridgewater (1): powerpc: Fix mpic_resume on early G5 macs Anton Blanchard (1): powerpc: Move kdump default base address to 64MB on 64bit Benjamin Herrenschmidt (1): Merge commit 'kumar/merge' into merge Christoph Egger (1): powerpc: Remove dead CONFIG_HIGHPTE Christoph Hellwig (1): powerpc: Unconditionally enabled irq stacks Grant Likely (1): powerpc: Disable CONFIG_SYSFS_DEPRECATED Kumar Gala (1): powerpc/fsl-booke: Move loadcam_entry back to asm code to fix SMP ftrace Li Yang (1): powerpc/fsl-booke: Fix InstructionTLBError execute permission check Matt Evans (1): powerpc/kexec: Wait for online/possible CPUs only. Milton Miller (1): powerpc: rtas_flash needs to use rtas_data_buf Paul Mackerras (1): powerpc/boot: Remove addRamdisk.c since it is now unused arch/powerpc/Kconfig.debug |7 - arch/powerpc/boot/Makefile |2 +- arch/powerpc/boot/addRamDisk.c | 311 -- arch/powerpc/configs/40x/acadia_defconfig|3 +- arch/powerpc/configs/40x/ep405_defconfig |3 +- arch/powerpc/configs/40x/hcu4_defconfig |3 +- arch/powerpc/configs/40x/kilauea_defconfig |3 +- arch/powerpc/configs/40x/makalu_defconfig|3 +- arch/powerpc/configs/40x/virtex_defconfig|3 +- arch/powerpc/configs/40x/walnut_defconfig|3 +- arch/powerpc/configs/44x/arches_defconfig|3 +- arch/powerpc/configs/44x/bamboo_defconfig|3 +- arch/powerpc/configs/44x/canyonlands_defconfig |3 +- arch/powerpc/configs/44x/ebony_defconfig |3 +- arch/powerpc/configs/44x/eiger_defconfig |3 +- arch/powerpc/configs/44x/katmai_defconfig|3 +- arch/powerpc/configs/44x/rainier_defconfig |3 +- arch/powerpc/configs/44x/redwood_defconfig |3 +- arch/powerpc/configs/44x/sam440ep_defconfig |3 +- arch/powerpc/configs/44x/sequoia_defconfig |3 +- arch/powerpc/configs/44x/taishan_defconfig |3 +- arch/powerpc/configs/44x/virtex5_defconfig |3 +- arch/powerpc/configs/52xx/cm5200_defconfig |3 +- arch/powerpc/configs/52xx/lite5200b_defconfig|3 +- arch/powerpc/configs/52xx/motionpro_defconfig|3 +- arch/powerpc/configs/52xx/pcm030_defconfig |3 +- arch/powerpc/configs/52xx/tqm5200_defconfig |3 +- arch/powerpc/configs/86xx/gef_ppc9a_defconfig|3 +- arch/powerpc/configs/86xx/gef_sbc310_defconfig |3 +- arch/powerpc/configs/86xx/gef_sbc610_defconfig |3 +- arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig |3 +- arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig |3 +- arch/powerpc/configs/86xx/sbc8641d_defconfig |3 +- arch/powerpc/configs/adder875_defconfig |3 +- arch/powerpc/configs/amigaone_defconfig |3 +- arch/powerpc/configs/c2k_defconfig |3 +- arch/powerpc/configs/cell_defconfig |3 +- arch/powerpc/configs/celleb_defconfig|3 +- arch/powerpc/configs/chrp32_defconfig|3 +- arch/powerpc/configs/ep8248e_defconfig |3 +- arch/powerpc/configs/ep88xc_defconfig|3 +- arch/powerpc/configs/g5_defconfig|3 +- arch/powerpc/configs/gamecube_defconfig |3 +- arch/powerpc/configs/holly_defconfig |1 - arch/powerpc/configs/iseries_defconfig |3 +- arch/powerpc/configs/linkstation_defconfig |3 +- arch/powerpc/configs/maple_defconfig |3 +- arch/powerpc/configs/mgcoge_defconfig|3 +- arch/powerpc/configs/mgsuvd_defconfig|3 +- arch/powerpc/configs/mpc512x_defconfig |3 +- arch/powerpc/configs/mpc5200_defconfig |3 +- arch/powerpc/configs/mpc7448_hpc2_defconfig |3 +- arch/powerpc/configs/pasemi_defconfig|3 +- arch/powerpc/configs/pmac32_defconfig|3 +- arch/powerpc/configs/ppc40x_defconfig|3 +- arch/powerpc/configs/ppc44x_defconfig|3 +- arch/powerpc/configs/ppc64_defconfig |3 +- arch/powerpc/configs/ppc64e_defconfig|3 +- arch/powerpc/configs/pq2fads_defconfig |3 +- arch/powerpc/configs/prpmc2800_defconfig |3 +-
Re: Re:Re: PCIe bus seems work while 'dma' can't under linux
On Tue, 2010-06-15 at 15:05 +0800, jxnuxdy wrote: Thanks Benjamin, the regions don't display as what we expect, that's why we suspect if there any configuration probelms in CPU host bridge, but we changed the uboot/linux a lot, seems take no effect on that problems. We use CPU MPC8544, and connect two PCIE devices to CPU PCIE1 and PCIE2 directly without a extended PCIE bridge, so we disabled PCIE3 and PCI controlers in uboot level. More settings pls take a look at the attach file log.txt. I'm not familiar with those freescale parts, so I'll let others comment on your settings since it's most likely to be where the problem is. Cheers, Ben. Many thanks, Denny 在2010-06-11 15:21:24,Benjamin Herrenschmidt b...@kernel.crashing.org 写道: On Fri, 2010-06-11 at 09:30 +0800, jxnuxdy wrote: Hi guys, I encountered a PCIe problem under linux, the two PCIe bus on my board seems work, at least I can access the registers through the PCIe bus, however the dma for the PCIe bus can't work, so I just dumped the pci device, but I am curiously to find there is no regions displayed on PCIe controlers, why? is it relate with my 'dma' issue then? It would help if you told us a bit more what the HW is, what you are doing with it, etc... IE. What is your host, what is your device, what platform, etc... DMA should work provided that your platform code sets it up properly. The DMA regions don't appear in /proc/pci or lspci. Cheers, Ben. bash-2.04# cat /proc/pci PCI devices found: Bus 0, device 0, function 0: Class 0b20 Header Type 01: PCI device 1957:0032 (rev 17). Bus 1, device 0, function 0: Class 0580 Header Type 00: PCI device 11ab:db90 (rev 1). Prefetchable 64 bit memory at 0x8000 [0x800f]. Prefetchable 64 bit memory at 0x8400 [0x87ff]. Bus 9, device 0, function 0: Class 0b20 Header Type 01: PCI device 1957:0032 (rev 17). Bus 10, device 0, function 0: Class 0580 Header Type 00: PCI device 11ab:db90 (rev 1). Prefetchable 64 bit memory at 0xa000 [0xa00f]. Prefetchable 64 bit memory at 0xa400 [0xa7ff]. bash-2.04# lspci -vv 00:00.0 Power PC: Unknown device 1957:0032 (rev 11) !!! Invalid class 0b20 for header type 01 Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- Status: Cap+ 66Mhz- UDF- FastB2B- ParErr- DEVSEL=fast TAbort- TAbort- MAbort- SERR- PERR- Latency: 0, cache line size 08 Bus: primary=00, secondary=01, subordinate=06, sec-latency=0 I/O behind bridge: -0fff Memory behind bridge: 8000-9fff BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- Reset- FastB2B- Capabilities: [44] Power Management version 2 Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+) Status: D0 PME-Enable- DSel=0 DScale=0 PME- Capabilities: [4c] #10 [0041] 01:00.0 Memory controller: Galileo Technology Ltd.: Unknown device db90 (rev 01) Subsystem: Galileo Technology Ltd.: Unknown device 11ab Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- Status: Cap+ 66Mhz- UDF- FastB2B- ParErr- DEVSEL=fast TAbort- TAbort- MAbort- SERR- PERR- Latency: 0, cache line size 08 Interrupt: pin A routed to IRQ 0 Region 0: Memory at 8000 (64-bit, prefetchable) [size=1M] Region 2: Memory at 8400 (64-bit, prefetchable) [size=64M] Capabilities: [40] Power Management version 2 Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-) Status: D0 PME-Enable- DSel=0 DScale=0 PME- Capabilities: [50] Message Signalled Interrupts: 64bit+ Queue=0/0 Enable- Address: Data: Capabilities: [60] #10 [0011] 09:00.0 Power PC: Unknown device 1957:0032 (rev 11) !!! Invalid class 0b20 for header type 01 Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- Status: Cap+ 66Mhz- UDF- FastB2B- ParErr- DEVSEL=fast TAbort- TAbort- MAbort- SERR- PERR- Latency: 0, cache line size 08 Bus: primary=00, secondary=0a, subordinate=0f, sec-latency=0 I/O behind bridge: -0fff Memory behind bridge: a000-bfff BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- Reset- FastB2B- Capabilities: [44] Power Management version 2 Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+) Status: D0 PME-Enable- DSel=0
[PATCH 1/2] ehea: fix delayed packet processing
In the eHEA poll function an rmb() is required. Without that some packets on the receive queue are not seen and thus delayed until the next interrupt is handled for the same receive queue. Signed-off-by: Jan-Bernd Themann them...@de.ibm.com --- Patch created against 2.6.35-rc3 drivers/net/ehea/ehea_main.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index f547894..fd890fa 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -867,6 +867,7 @@ static int ehea_poll(struct napi_struct *napi, int budget) ehea_reset_cq_ep(pr-send_cq); ehea_reset_cq_n1(pr-recv_cq); ehea_reset_cq_n1(pr-send_cq); + rmb(); cqe = ehea_poll_rq1(pr-qp, wqe_index); cqe_skb = ehea_poll_cq(pr-send_cq); -- 1.7.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/2] ehea: Fix kernel deadlock in DLPAR-mem processing
Port reset operations and memory add/remove operations need to be serialized to avoid a kernel deadlock. The deadlock is caused by calling the napi_disable() function twice. Therefore we have to employ the dlpar_mem_lock in the ehea_reset_port function as well Signed-off-by: Jan-Bernd Themann them...@de.ibm.com --- created against kernel-2.6.35-rc3 drivers/net/ehea/ehea.h |2 +- drivers/net/ehea/ehea_main.c |8 +++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 0630980..0060e42 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include asm/io.h #define DRV_NAME ehea -#define DRV_VERSIONEHEA_0103 +#define DRV_VERSIONEHEA_0105 /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index fd890fa..8b92acb 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -2860,6 +2860,7 @@ static void ehea_reset_port(struct work_struct *work) container_of(work, struct ehea_port, reset_task); struct net_device *dev = port-netdev; + mutex_lock(dlpar_mem_lock); port-resets++; mutex_lock(port-port_lock); netif_stop_queue(dev); @@ -2882,6 +2883,7 @@ static void ehea_reset_port(struct work_struct *work) netif_wake_queue(dev); out: mutex_unlock(port-port_lock); + mutex_unlock(dlpar_mem_lock); } static void ehea_rereg_mrs(struct work_struct *work) @@ -3543,10 +3545,7 @@ static int ehea_mem_notifier(struct notifier_block *nb, int ret = NOTIFY_BAD; struct memory_notify *arg = data; - if (!mutex_trylock(dlpar_mem_lock)) { - ehea_info(ehea_mem_notifier must not be called parallelized); - goto out; - } + mutex_lock(dlpar_mem_lock); switch (action) { case MEM_CANCEL_OFFLINE: @@ -3575,7 +3574,6 @@ static int ehea_mem_notifier(struct notifier_block *nb, out_unlock: mutex_unlock(dlpar_mem_lock); -out: return ret; } -- 1.7.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 0/2 v3] mpc5200 ac97 gpio reset
These patches reimplement the reset fuction in the ac97 to use gpio pins instead of using the mpc5200 ac97 reset functionality in the psc. This avoids a problem in which attached ac97 devices go into test mode appear unresponsive. These patches were tested on a pcm030 baseboard and on custom hardware with a wm9715 audio codec/touchscreen controller. Eric Millbrandt --- changes since v1 - Refactored to manipulate port_config and gpio pins internally instead of exporting an API. - Amended commit message with comments from Mark Brown - Refactored to move the port_config manipulation to platform code. - Remove the gpio pins from the device-tree changes since v2 - Factored out gpiolib calls, write to the gpio registers directly - Remove redundant checks around call to mpc5200_psc_ac97_gpio_reset() Eric Millbrandt (2): powerpc/5200: add mpc5200_psc_ac97_gpio_reset sound/soc: mpc5200_psc_ac97: Use gpio pins for cold reset arch/powerpc/include/asm/mpc52xx.h |1 + arch/powerpc/include/asm/mpc52xx_psc.h |1 + arch/powerpc/platforms/52xx/mpc52xx_common.c | 113 ++ sound/soc/fsl/mpc5200_psc_ac97.c | 22 - 4 files changed, 133 insertions(+), 4 deletions(-) -DISCLAIMER: an automatically appended disclaimer may follow. By posting- -to a public e-mail mailing list I hereby grant permission to distribute- -and copy this message.- This e-mail and the information, including any attachments, it contains are intended to be a confidential communication only to the person or entity to whom it is addressed and may contain information that is privileged. If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please immediately notify the sender and destroy the original message. Thank you. Please consider the environment before printing this email. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/2 v3] powerpc/5200: add mpc5200_psc_ac97_gpio_reset
Work around a silicon bug in the ac97 reset functionality of the mpc5200(b). The implementation of the ac97 cold reset is flawed. If the sync and output lines are high when reset is asserted the attached ac97 device may go into test mode. Avoid this by reconfiguring the psc to gpio mode and generating the reset manually. From MPC5200B User's Manual: Some AC97 devices goes to a test mode, if the Sync line is high during the Res line is low (reset phase). To avoid this behavior the Sync line must be also forced to zero during the reset phase. To do that, the pin muxing should switch to GPIO mode and the GPIO control register should be used to control the output lines. Signed-off-by: Eric Millbrandt emillbra...@dekaresearch.com --- changes since v1 - Refactored to manipulate port_config and gpio pins internally instead of exporting an API. changes since v2 - Factored out gpiolib calls, write to the gpio registers directly arch/powerpc/include/asm/mpc52xx.h |1 + arch/powerpc/include/asm/mpc52xx_psc.h |1 + arch/powerpc/platforms/52xx/mpc52xx_common.c | 113 ++ 3 files changed, 115 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/include/asm/mpc52xx.h b/arch/powerpc/include/asm/mpc52xx.h index b664ce7..1f41382 100644 --- a/arch/powerpc/include/asm/mpc52xx.h +++ b/arch/powerpc/include/asm/mpc52xx.h @@ -271,6 +271,7 @@ struct mpc52xx_intr { /* mpc52xx_common.c */ extern void mpc5200_setup_xlb_arbiter(void); extern void mpc52xx_declare_of_platform_devices(void); +extern int mpc5200_psc_ac97_gpio_reset(int psc_number); extern void mpc52xx_map_common_devices(void); extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv); extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node); diff --git a/arch/powerpc/include/asm/mpc52xx_psc.h b/arch/powerpc/include/asm/mpc52xx_psc.h index ecc4fc6..2966df6 100644 --- a/arch/powerpc/include/asm/mpc52xx_psc.h +++ b/arch/powerpc/include/asm/mpc52xx_psc.h @@ -131,6 +131,7 @@ #define MPC52xx_PSC_SICR_SIM_FIR (0x6 24) #define MPC52xx_PSC_SICR_SIM_CODEC_24 (0x7 24) #define MPC52xx_PSC_SICR_SIM_CODEC_32 (0xf 24) +#define MPC52xx_PSC_SICR_ACRB (0x8 24) #define MPC52xx_PSC_SICR_AWR (1 30) #define MPC52xx_PSC_SICR_GENCLK(1 23) #define MPC52xx_PSC_SICR_I2S (1 22) diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index a46bad0..116d461 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -12,9 +12,11 @@ #undef DEBUG +#include linux/gpio.h #include linux/kernel.h #include linux/spinlock.h #include linux/of_platform.h +#include linux/of_gpio.h #include asm/io.h #include asm/prom.h #include asm/mpc52xx.h @@ -82,6 +84,14 @@ mpc5200_setup_xlb_arbiter(void) iounmap(xlb); } +/* + * This variable is mapped in mpc52xx_map_common_devices and + * used in mpc5200_psc_ac97_gpio_reset(). + */ +static DEFINE_SPINLOCK(gpio_lock); +struct mpc52xx_gpio __iomem *simple_gpio; +struct mpc52xx_gpio_wkup __iomem *wkup_gpio; + /** * mpc52xx_declare_of_platform_devices: register internal devices and children * of the localplus bus to the of_platform @@ -109,6 +119,19 @@ static struct of_device_id mpc52xx_cdm_ids[] __initdata = { { .compatible = mpc5200-cdm, }, /* old */ {} }; +static const struct of_device_id mpc52xx_gpio_simple[] = { + { + .compatible = fsl,mpc5200-gpio, + }, + {} +}; +static const struct of_device_id mpc52xx_gpio_wkup[] = { + { + .compatible = fsl,mpc5200-gpio-wkup, + }, + {} +}; + /** * mpc52xx_map_common_devices: iomap devices required by common code @@ -135,6 +158,16 @@ mpc52xx_map_common_devices(void) np = of_find_matching_node(NULL, mpc52xx_cdm_ids); mpc52xx_cdm = of_iomap(np, 0); of_node_put(np); + + /* simple_gpio registers */ + np = of_find_matching_node(NULL, mpc52xx_gpio_simple); + simple_gpio = of_iomap(np, 0); + of_node_put(np); + + /* wkup_gpio registers */ + np = of_find_matching_node(NULL, mpc52xx_gpio_wkup); + wkup_gpio = of_iomap(np, 0); + of_node_put(np); } /** @@ -233,3 +266,83 @@ mpc52xx_restart(char *cmd) while (1); } + +#define PSC1_RESET 0x1 +#define PSC1_SYNC 0x4 +#define PSC1_SDATA_OUT 0x1 +#define PSC2_RESET 0x2 +#define PSC2_SYNC (0x44) +#define PSC2_SDATA_OUT (0x14) +#define MPC52xx_GPIO_PSC1_MASK 0x7 +#define MPC52xx_GPIO_PSC2_MASK (0x74) + +/** + * mpc5200_psc_ac97_gpio_reset: Use gpio pins to reset the ac97 bus + * + * @psc: psc number to reset (only psc 1 and 2 support ac97) + */ +int mpc5200_psc_ac97_gpio_reset(int psc_number) +{ + unsigned long flags; + u32 gpio; + u32 mux; +
[PATCH 2/2 v4] sound/soc: mpc5200_psc_ac97: Use gpio pins for cold reset
Call the gpio reset platform function instead of using the flawed ac97 functionality of the MPC5200(b) From MPC5200B User's Manual: Some AC97 devices goes to a test mode, if the Sync line is high during the Res line is low (reset phase). To avoid this behavior the Sync line must be also forced to zero during the reset phase. To do that, the pin muxing should switch to GPIO mode and the GPIO control register should be used to control the output lines. Signed-off-by: Eric Millbrandt emillbra...@dekaresearch.com --- changes since v1 - Amended with comments from Mark Brown - Fall back to the original reset implementation if no gpio pins are defined in the device tree changes since v2 - Refactored to move the port_config manipulation to platform code. - Remove the gpio pins from the device-tree changes since v3 - Remove redundant checks around call to mpc5200_psc_ac97_gpio_reset() sound/soc/fsl/mpc5200_psc_ac97.c | 22 ++ 1 files changed, 18 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index e2ee220..e7f5d50 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -20,6 +20,7 @@ #include asm/time.h #include asm/delay.h +#include asm/mpc52xx.h #include asm/mpc52xx_psc.h #include mpc5200_dma.h @@ -100,19 +101,32 @@ static void psc_ac97_warm_reset(struct snd_ac97 *ac97) { struct mpc52xx_psc __iomem *regs = psc_dma-psc_regs; + mutex_lock(psc_dma-mutex); + out_be32(regs-sicr, psc_dma-sicr | MPC52xx_PSC_SICR_AWR); udelay(3); out_be32(regs-sicr, psc_dma-sicr); + + mutex_unlock(psc_dma-mutex); } static void psc_ac97_cold_reset(struct snd_ac97 *ac97) { struct mpc52xx_psc __iomem *regs = psc_dma-psc_regs; - /* Do a cold reset */ - out_8(regs-op1, MPC52xx_PSC_OP_RES); - udelay(10); - out_8(regs-op0, MPC52xx_PSC_OP_RES); + mutex_lock(psc_dma-mutex); + dev_dbg(psc_dma-dev, cold reset\n); + + mpc5200_psc_ac97_gpio_reset(psc_dma-id); + + /* Notify the PSC that a reset has occurred */ + out_be32(regs-sicr, psc_dma-sicr | MPC52xx_PSC_SICR_ACRB); + + /* Re-enable RX and TX */ + out_8(regs-command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); + + mutex_unlock(psc_dma-mutex); + msleep(1); psc_ac97_warm_reset(ac97); } -- -DISCLAIMER: an automatically appended disclaimer may follow. By posting- -to a public e-mail mailing list I hereby grant permission to distribute- -and copy this message.- 1.6.3.1 This e-mail and the information, including any attachments, it contains are intended to be a confidential communication only to the person or entity to whom it is addressed and may contain information that is privileged. If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please immediately notify the sender and destroy the original message. Thank you. Please consider the environment before printing this email. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v4 00/12] ptp: IEEE 1588 clock support
Now and again there has been talk on the netdev list of adding PTP support into Linux. One part of the picture is already in place, the SO_TIMESTAMPING API for hardware time stamping. This patch set offers the missing second part needed for complete IEEE 1588 support. The only feature still to be implemented is the hook into the PPS subsystem, to synchronize the Linux clock to the PTP clock. The first seven patches concern phylib. A new generation of PHYs with timestamping capabilities is appearing on the market. In order to support hardware timestamping on these devices in Linux, a number of adjustments will have to be made in the PHY subsystem. The reasons for the changes are explained inline at the top of the patches. The last five patches provide the PTP subsystem itself. * Why all the CCs? 1. The patches probably should go through netdev. 2. One driver is for PowerPC, and adds device tree stuff. 3. One driver is for the ARM Xscale IXP465 * Open Issues: ** DP83640 In order to make this work, three lines must be added into the MAC driver. Since this PHY can be connected to almost any MAC, I did not do anything about that. If you have the DP83640 and want to try the driver, you need to add three lines to your MAC driver. 1. Before mdio_register, add bus-locktype = MDIOBUS_ATOMIC_RW; 2. In the .ndo_start_xmit function, add skb_tx_timestamp() 3. In the NAPI poll function, add skb_rx_timestamp() ** IXP465 I do not know how to correctly choose the timestamp channel based on the port identifier: #define PORT2CHANNEL(p) 1 /* * PHYSICAL_ID(p-id) ? * TODO - Figure out correct mapping. */ * Patch ChangeLog ** v4 *** general - Added a clock driver for the National Semiconductor PHYTER. - Added a clock driver for the Intel IXP465. - Made more stylish according to checkstyle.pl. *** gianfar - Replace device_type and model with compatible string (fsl,etsec-ptp) - Register only one interrupt, since others are superfluous. - Combine ptp clock instance with private variable structure. - ISR now returns NONE or HANDLED properly. - Print error message if something is missing from the device nodes. ** v3 *** general - Added documentation on writing clock drivers. - Added the ioctls for the ancillary clock features. - Changed wrong subsys_initcall() to module_init() in clock drivers. - Removed the (too coarse) character device mutex. - Setting the clock now requires CAP_SYS_TIME. *** gianfar - Added alarm feature. - Added device tree node binding description. - Added fine grain locking of the clock registers. - Added the external time stamp feature. - Added white space for better style. - Coverted base+offset to structure pointers for register access. - When removing the driver, we now disable all PTP functions. ** v2 - Changed clock list from a static array into a dynamic list. Also, use a bitmap to manage the clock's minor numbers. - Replaced character device semaphore with a mutex. - Drop .ko from module names in Kbuild help. - Replace deprecated unifdef-y with header-y for user space header file. - Added links to both of the ptpd patches on sourceforge. - Gianfar driver now gets parameters from device tree. - Added API documentation to Documentation/ptp/ptp.txt Looking forward to your feedback, Richard Richard Cochran (12): phylib: preserve ifreq parameter when calling generic phy_mii_ioctl() phylib: do not filter phy_mii_ioctl() phylib: add a driver method for the SIOCSHWTSTAMP ioctl. phylib: add a way to make PHY time stamps possible. phylib: Allow reading and writing a mii bus from atomic context. ptp: add a BPF to help drivers detect PTP packets. phylib: support the National Semiconductor DP83640 PHY. ptp: Added a brand new class driver for ptp clocks. ptp: Added a clock that uses the Linux system time. ptp: Added a clock that uses the eTSEC found on the MPC85xx. ptp: Added a clock driver for the IXP46x. ptp: Added a clock driver for the National Semiconductor PHYTER. Documentation/powerpc/dts-bindings/fsl/tsec.txt | 54 ++ Documentation/ptp/ptp.txt | 95 Documentation/ptp/testptp.c | 269 ++ Documentation/ptp/testptp.mk| 33 ++ arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h | 67 +++ arch/powerpc/boot/dts/mpc8313erdb.dts | 13 + arch/powerpc/boot/dts/p2020ds.dts | 13 + arch/powerpc/boot/dts/p2020rdb.dts | 13 + drivers/Kconfig |2 + drivers/Makefile|1 + drivers/net/Makefile|1 + drivers/net/arm/ixp4xx_eth.c| 197 - drivers/net/au1000_eth.c|2 +- drivers/net/bcm63xx_enet.c
[PATCH 01/12] phylib: preserve ifreq parameter when calling generic phy_mii_ioctl()
The phy_mii_ioctl() function unnecessarily throws away the original ifreq. We need access to the ifreq in order to support PHYs that can perform hardware time stamping. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- drivers/net/arm/ixp4xx_eth.c |3 ++- drivers/net/au1000_eth.c |2 +- drivers/net/bcm63xx_enet.c |2 +- drivers/net/cpmac.c|2 +- drivers/net/dnet.c |2 +- drivers/net/ethoc.c|2 +- drivers/net/fec.c |2 +- drivers/net/fec_mpc52xx.c |2 +- drivers/net/fs_enet/fs_enet-main.c |3 +-- drivers/net/gianfar.c |2 +- drivers/net/macb.c |2 +- drivers/net/mv643xx_eth.c |2 +- drivers/net/octeon/octeon_mgmt.c |2 +- drivers/net/phy/phy.c |3 ++- drivers/net/sb1250-mac.c |2 +- drivers/net/sh_eth.c |2 +- drivers/net/smsc911x.c |2 +- drivers/net/smsc9420.c |2 +- drivers/net/stmmac/stmmac_main.c |2 +- drivers/net/tc35815.c |2 +- drivers/net/tg3.c |2 +- drivers/staging/octeon/ethernet-mdio.c |2 +- include/linux/phy.h|2 +- net/dsa/slave.c|3 +-- 24 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index ee2f842..4f1cc71 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -782,7 +782,8 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) if (!netif_running(dev)) return -EINVAL; - return phy_mii_ioctl(port-phydev, if_mii(req), cmd); + + return phy_mii_ioctl(port-phydev, req, cmd); } /* ethtool support */ diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index ece6128..386d4fe 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -978,7 +978,7 @@ static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!aup-phy_dev) return -EINVAL; /* PHY not controllable */ - return phy_mii_ioctl(aup-phy_dev, if_mii(rq), cmd); + return phy_mii_ioctl(aup-phy_dev, rq, cmd); } static const struct net_device_ops au1000_netdev_ops = { diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index faf5add..0d2c5da 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -1496,7 +1496,7 @@ static int bcm_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (priv-has_phy) { if (!priv-phydev) return -ENODEV; - return phy_mii_ioctl(priv-phydev, if_mii(rq), cmd); + return phy_mii_ioctl(priv-phydev, rq, cmd); } else { struct mii_if_info mii; diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 3c58db5..d4c5ca4 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -848,7 +848,7 @@ static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EINVAL; if ((cmd == SIOCGMIIPHY) || (cmd == SIOCGMIIREG) || (cmd == SIOCSMIIREG)) - return phy_mii_ioctl(priv-phy, if_mii(ifr), cmd); + return phy_mii_ioctl(priv-phy, ifr, cmd); return -EOPNOTSUPP; } diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index 8b0f50b..4ea7141 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -797,7 +797,7 @@ static int dnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!phydev) return -ENODEV; - return phy_mii_ioctl(phydev, if_mii(rq), cmd); + return phy_mii_ioctl(phydev, rq, cmd); } static void dnet_get_drvinfo(struct net_device *dev, diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index 6ed2df1..8102f01 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -734,7 +734,7 @@ static int ethoc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) phy = priv-phy; } - return phy_mii_ioctl(phy, mdio, cmd); + return phy_mii_ioctl(phy, ifr, cmd); } static int ethoc_config(struct net_device *dev, struct ifmap *map) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index a3cae4e..f24f49e 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -828,7 +828,7 @@ static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!phydev) return -ENODEV; - return phy_mii_ioctl(phydev, if_mii(rq), cmd); + return phy_mii_ioctl(phydev, rq, cmd); } static void fec_enet_free_buffers(struct net_device *dev) diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index 25e6cc6..fdbf148 100644 ---
[PATCH 02/12] phylib: do not filter phy_mii_ioctl()
Two maverick drivers filter the ioctl commands passed to phy_mii_ioctl(). This is unnecessary since phylib will check the command in any case. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- drivers/net/cpmac.c |5 + drivers/net/stmmac/stmmac_main.c | 22 -- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index d4c5ca4..0e47ca1 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -846,11 +846,8 @@ static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EINVAL; if (!priv-phy) return -EINVAL; - if ((cmd == SIOCGMIIPHY) || (cmd == SIOCGMIIREG) || - (cmd == SIOCSMIIREG)) - return phy_mii_ioctl(priv-phy, ifr, cmd); - return -EOPNOTSUPP; + return phy_mii_ioctl(priv-phy, ifr, cmd); } static int cpmac_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 6af7471..acf0616 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -1437,24 +1437,18 @@ static void stmmac_poll_controller(struct net_device *dev) static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct stmmac_priv *priv = netdev_priv(dev); - int ret = -EOPNOTSUPP; + int ret; if (!netif_running(dev)) return -EINVAL; - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - if (!priv-phydev) - return -EINVAL; - - spin_lock(priv-lock); - ret = phy_mii_ioctl(priv-phydev, rq, cmd); - spin_unlock(priv-lock); - default: - break; - } + if (!priv-phydev) + return -EINVAL; + + spin_lock(priv-lock); + ret = phy_mii_ioctl(priv-phydev, rq, cmd); + spin_unlock(priv-lock); + return ret; } -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 03/12] phylib: add a driver method for the SIOCSHWTSTAMP ioctl.
This patch adds a phy driver method for configuring hardware time stamping. Drivers may optionally implement this function. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- drivers/net/phy/phy.c |5 + include/linux/phy.h |3 +++ 2 files changed, 8 insertions(+), 0 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index bd88d81..5130db8 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -361,6 +361,11 @@ int phy_mii_ioctl(struct phy_device *phydev, } break; + case SIOCSHWTSTAMP: + if (phydev-drv-hwtstamp) + return phydev-drv-hwtstamp(phydev, ifr); + /* fall through */ + default: return -EOPNOTSUPP; } diff --git a/include/linux/phy.h b/include/linux/phy.h index d63736a..a5e9df1 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -402,6 +402,9 @@ struct phy_driver { /* Clears up any memory if needed */ void (*remove)(struct phy_device *phydev); + /* Handles SIOCSHWTSTAMP ioctl for hardware time stamping. */ + int (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr); + struct device_driver driver; }; #define to_phy_driver(d) container_of(d, struct phy_driver, driver) -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 04/12] phylib: add a way to make PHY time stamps possible.
This patch adds a new networking option to allow hardware time stamps from PHY devices. Using PHY time stamps will still require adding two inline function calls to each MAC driver. The CONFIG option makes these calls safe to add, since the calls become NOOPs when the option is disabled. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- include/linux/phy.h|4 include/linux/skbuff.h | 32 net/Kconfig| 11 +++ 3 files changed, 47 insertions(+), 0 deletions(-) diff --git a/include/linux/phy.h b/include/linux/phy.h index a5e9df1..7a8caac 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -234,6 +234,8 @@ enum phy_state { PHY_RESUMING }; +struct sk_buff; + /* phy_device: An instance of a PHY * * drv: Pointer to the driver for this PHY instance @@ -404,6 +406,8 @@ struct phy_driver { /* Handles SIOCSHWTSTAMP ioctl for hardware time stamping. */ int (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr); + int (*rxtstamp)(struct phy_device *phydev, struct sk_buff *skb); + int (*txtstamp)(struct phy_device *phydev, struct sk_buff *skb); struct device_driver driver; }; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 645e78d..7b650d4 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -29,6 +29,7 @@ #include linux/rcupdate.h #include linux/dmaengine.h #include linux/hrtimer.h +#include linux/phy.h /* Don't change this without changing skb_csum_unnecessary! */ #define CHECKSUM_NONE 0 @@ -1942,6 +1943,37 @@ static inline ktime_t net_invalid_timestamp(void) extern void skb_tstamp_tx(struct sk_buff *orig_skb, struct skb_shared_hwtstamps *hwtstamps); +#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING + +static inline void skb_tx_timetamp(struct phy_device *phy, struct sk_buff *skb) +{ + union skb_shared_tx *shtx = skb_tx(skb); + + if (shtx-hardware phy phy-drv-txtstamp) + phy-drv-txtstamp(phy, skb); + + if (shtx-software !shtx-in_progress) + skb_tstamp_tx(skb, NULL); +} + +static inline void skb_rx_timetamp(struct phy_device *phy, struct sk_buff *skb) +{ + if (phy phy-drv-rxtstamp) + phy-drv-rxtstamp(phy, skb); +} + +#else /* CONFIG_NETWORK_PHY_TIMESTAMPING */ + +static inline void skb_tx_timetamp(struct phy_device *phy, struct sk_buff *skb) +{ +} + +static inline void skb_rx_timetamp(struct phy_device *phy, struct sk_buff *skb) +{ +} + +#endif /* !CONFIG_NETWORK_PHY_TIMESTAMPING */ + extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len); extern __sum16 __skb_checksum_complete(struct sk_buff *skb); diff --git a/net/Kconfig b/net/Kconfig index 0d68b40..3fa7ae3 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -86,6 +86,17 @@ config NETWORK_SECMARK to nfmark, but designated for security purposes. If you are unsure how to answer this question, answer N. +config NETWORK_PHY_TIMESTAMPING + bool Timestamping in PHY devices + depends on EXPERIMENTAL + help + This allows timestamping of network packets by PHYs with + hardware timestamping capabilities. This option adds some + overhead in the transmit and receive paths. Note that this + option also requires support in the MAC driver. + + If you are unsure how to answer this question, answer N. + menuconfig NETFILTER bool Network packet filtering framework (Netfilter) ---help--- -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 05/12] phylib: Allow reading and writing a mii bus from atomic context.
In order to support hardware time stamping from a PHY, it is necessary to read from the PHY while running in_interrupt(). This patch allows a mii bus to operate in an atomic context. An mii_bus driver may declare itself capable for this mode. Drivers which do not do this will remain with the default that bus operations may sleep. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- drivers/net/phy/mdio_bus.c | 35 --- include/linux/phy.h| 13 +++-- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 6a6b819..441be7d 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -36,6 +36,22 @@ #include asm/irq.h #include asm/uaccess.h +static inline void mdiobus_lock(struct mii_bus *bus) +{ + if (MDIOBUS_SLEEPS_RW == bus-locktype) + mutex_lock(bus-mdio_lock.m); + else + spin_lock(bus-mdio_lock.s); +} + +static inline void mdiobus_unlock(struct mii_bus *bus) +{ + if (MDIOBUS_SLEEPS_RW == bus-locktype) + mutex_unlock(bus-mdio_lock.m); + else + spin_unlock(bus-mdio_lock.s); +} + /** * mdiobus_alloc - allocate a mii_bus structure * @@ -107,7 +123,10 @@ int mdiobus_register(struct mii_bus *bus) return -EINVAL; } - mutex_init(bus-mdio_lock); + if (MDIOBUS_SLEEPS_RW == bus-locktype) + mutex_init(bus-mdio_lock.m); + else + spin_lock_init(bus-mdio_lock.s); if (bus-reset) bus-reset(bus); @@ -212,11 +231,12 @@ int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) { int retval; - BUG_ON(in_interrupt()); + if (MDIOBUS_SLEEPS_RW == bus-locktype) + BUG_ON(in_interrupt()); - mutex_lock(bus-mdio_lock); + mdiobus_lock(bus); retval = bus-read(bus, addr, regnum); - mutex_unlock(bus-mdio_lock); + mdiobus_unlock(bus); return retval; } @@ -237,11 +257,12 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) { int err; - BUG_ON(in_interrupt()); + if (MDIOBUS_SLEEPS_RW == bus-locktype) + BUG_ON(in_interrupt()); - mutex_lock(bus-mdio_lock); + mdiobus_lock(bus); err = bus-write(bus, addr, regnum, val); - mutex_unlock(bus-mdio_lock); + mdiobus_unlock(bus); return err; } diff --git a/include/linux/phy.h b/include/linux/phy.h index 7a8caac..352b030 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -98,11 +98,20 @@ struct mii_bus { int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val); int (*reset)(struct mii_bus *bus); + /* Indicates whether bus may be used from an atomic context. */ + enum { + MDIOBUS_SLEEPS_RW, + MDIOBUS_ATOMIC_RW + } locktype; + /* -* A lock to ensure that only one thing can read/write +* A lock or mutex to ensure that only one thing can read/write * the MDIO bus at a time */ - struct mutex mdio_lock; + union { + struct mutex m; + spinlock_t s; + } mdio_lock; struct device *parent; enum { -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 06/12] ptp: add a BPF to help drivers detect PTP packets.
Certain kinds of hardware time stamping units in both MACs and PHYs have the limitation that they can only time stamp PTP packets. Drivers for such hardware are left with the task of correctly matching skbs to time stamps. This patch adds a BPF that drivers can use to classify PTP packets when needed. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- include/linux/ptp_classify.h | 118 ++ 1 files changed, 118 insertions(+), 0 deletions(-) create mode 100644 include/linux/ptp_classify.h diff --git a/include/linux/ptp_classify.h b/include/linux/ptp_classify.h new file mode 100644 index 000..e68efc3 --- /dev/null +++ b/include/linux/ptp_classify.h @@ -0,0 +1,118 @@ +/* + * PTP 1588 support + * + * This file implements a BPF that recognizes PTP event messages. + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _PTP_CLASSIFY_H_ +#define _PTP_CLASSIFY_H_ + +#include linux/if_ether.h +#include linux/if_vlan.h +#include linux/filter.h +#ifdef __KERNEL__ +#include linux/in.h +#else +#include netinet/in.h +#endif + +#define PTP_CLASS_NONE 0x00 /* not a PTP event message */ +#define PTP_CLASS_V10x01 /* protocol version 1 */ +#define PTP_CLASS_V20x02 /* protocol version 2 */ +#define PTP_CLASS_VMASK 0x0f /* max protocol version is 15 */ +#define PTP_CLASS_IPV4 0x10 /* event in an IPV4 UDP packet */ +#define PTP_CLASS_IPV6 0x20 /* event in an IPV6 UDP packet */ +#define PTP_CLASS_L20x30 /* event in a L2 packet */ +#define PTP_CLASS_VLAN 0x40 /* event in a VLAN tagged L2 packet */ +#define PTP_CLASS_PMASK 0xf0 /* mask for the packet type field */ + +#define PTP_CLASS_V1_IPV4 (PTP_CLASS_V1 | PTP_CLASS_IPV4) +#define PTP_CLASS_V1_IPV6 (PTP_CLASS_V1 | PTP_CLASS_IPV6) /*probably DNE*/ +#define PTP_CLASS_V2_IPV4 (PTP_CLASS_V2 | PTP_CLASS_IPV4) +#define PTP_CLASS_V2_IPV6 (PTP_CLASS_V2 | PTP_CLASS_IPV6) +#define PTP_CLASS_V2_L2 (PTP_CLASS_V2 | PTP_CLASS_L2) +#define PTP_CLASS_V2_VLAN (PTP_CLASS_V2 | PTP_CLASS_VLAN) + +#define PTP_EV_PORT 319 + +#define OFF_ETYPE 12 +#define OFF_IHL14 +#define OFF_FRAG 20 +#define OFF_PROTO4 23 +#define OFF_NEXT 6 +#define OFF_UDP_DST2 + +#define IP6_HLEN 40 +#define UDP_HLEN 8 + +#define RELOFF_DST4(ETH_HLEN + OFF_UDP_DST) +#define OFF_DST6 (ETH_HLEN + IP6_HLEN + OFF_UDP_DST) +#define OFF_PTP6 (ETH_HLEN + IP6_HLEN + UDP_HLEN) + +#define OP_AND (BPF_ALU | BPF_AND | BPF_K) +#define OP_JEQ (BPF_JMP | BPF_JEQ | BPF_K) +#define OP_JSET(BPF_JMP | BPF_JSET | BPF_K) +#define OP_LDB (BPF_LD | BPF_B| BPF_ABS) +#define OP_LDH (BPF_LD | BPF_H| BPF_ABS) +#define OP_LDHI(BPF_LD | BPF_H| BPF_IND) +#define OP_LDX (BPF_LDX | BPF_B| BPF_MSH) +#define OP_OR (BPF_ALU | BPF_OR | BPF_K) +#define OP_RETA(BPF_RET | BPF_A) +#define OP_RETK(BPF_RET | BPF_K) + +#define PTP_FILTER \ + {OP_LDH,0, 0, OFF_ETYPE }, /* */ \ + {OP_JEQ,0, 12, ETH_P_IP}, /* f goto L20 */ \ + {OP_LDB,0, 0, OFF_PROTO4 }, /* */ \ + {OP_JEQ,0, 9, IPPROTO_UDP }, /* f goto L10 */ \ + {OP_LDH,0, 0, OFF_FRAG}, /* */ \ + {OP_JSET, 7, 0, 0x1fff }, /* t goto L11 */ \ + {OP_LDX,0, 0, OFF_IHL }, /* */ \ + {OP_LDHI, 0, 0, RELOFF_DST4 }, /* */ \ + {OP_JEQ,0, 4, PTP_EV_PORT }, /* f goto L12 */ \ + {OP_LDHI, 0, 0, ETH_HLEN + UDP_HLEN }, /* */ \ + {OP_AND,0, 0, PTP_CLASS_VMASK }, /* */ \ + {OP_OR, 0, 0, PTP_CLASS_IPV4 }, /* */ \ + {OP_RETA, 0, 0, 0 }, /* */ \ +/*L1x*/{OP_RETK, 0, 0, PTP_CLASS_NONE }, /* */ \ +/*L20*/{OP_JEQ,0, 9, ETH_P_IPV6 }, /* f goto L40 */ \ + {OP_LDB,0, 0, ETH_HLEN + OFF_NEXT }, /* */ \ + {OP_JEQ,0, 6,
[PATCH 07/12] phylib: support the National Semiconductor DP83640 PHY.
This patch adds a driver for the DP83640. This device is one of a new generation of PHYs able to time stamp PTP packets. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- drivers/net/phy/Kconfig |5 + drivers/net/phy/Makefile |1 + drivers/net/phy/dp83640.c | 439 + drivers/net/phy/dp83640_reg.h | 237 ++ 4 files changed, 682 insertions(+), 0 deletions(-) create mode 100644 drivers/net/phy/dp83640.c create mode 100644 drivers/net/phy/dp83640_reg.h diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index a527e37..430cab1 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -77,6 +77,11 @@ config NATIONAL_PHY ---help--- Currently supports the DP83865 PHY. +config DP83640_PHY + tristate Driver for the National Semiconductor DP83640 PHYTER + ---help--- + Supports the DP83640 PHYTER with IEEE 1588 features. + config STE10XP depends on PHYLIB tristate Driver for STMicroelectronics STe10Xp PHYs diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 13bebab..2333215 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_FIXED_PHY) += fixed.o obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o obj-$(CONFIG_MDIO_GPIO)+= mdio-gpio.o obj-$(CONFIG_NATIONAL_PHY) += national.o +obj-$(CONFIG_DP83640_PHY) += dp83640.o obj-$(CONFIG_STE10XP) += ste10Xp.o obj-$(CONFIG_MICREL_PHY) += micrel.o obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c new file mode 100644 index 000..a3217ea --- /dev/null +++ b/drivers/net/phy/dp83640.c @@ -0,0 +1,439 @@ +/* + * Driver for the National Semiconductor DP83640 PHYTER + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include linux/ethtool.h +#include linux/kernel.h +#include linux/list.h +#include linux/mii.h +#include linux/module.h +#include linux/net_tstamp.h +#include linux/netdevice.h +#include linux/phy.h +#include linux/ptp_classify.h + +#include dp83640_reg.h + +#define DP83640_PHY_ID 0x20005ce1 +#define PAGESEL0x13 +#define LAYER4 0x02 +#define LAYER2 0x01 +#define MAX_RXTS 8 + +struct rxts { + struct list_head list; + u64 ns; + unsigned long tmo; + u16 seqid; + u8 msgtype; + u16 hash; +}; + +struct dp83640_private { + int hwts_tx_en; + int hwts_rx_en; + int layer; + int version; + /* protects extended registers from concurrent access */ + spinlock_t extreg_lock; + int page; + /* list of rx timestamps */ + struct list_head rxts; + struct list_head pool; + struct rxts pool_data[MAX_RXTS]; +}; + +/* globals */ + +static struct sock_filter ptp_filter[] = { + PTP_FILTER +}; + +/* extended register access functions */ + +static int ext_read(struct phy_device *phydev, int page, u32 regnum) +{ + struct dp83640_private *dp83640 = phydev-priv; + int val; + + spin_lock(dp83640-extreg_lock); + + if (dp83640-page != page) { + phy_write(phydev, PAGESEL, page); + dp83640-page = page; + } + val = phy_read(phydev, regnum); + + spin_unlock(dp83640-extreg_lock); + + return val; +} + +static void ext_write(struct phy_device *phydev, int page, u32 regnum, u16 val) +{ + struct dp83640_private *dp83640 = phydev-priv; + + spin_lock(dp83640-extreg_lock); + + if (dp83640-page != page) { + phy_write(phydev, PAGESEL, page); + dp83640-page = page; + } + phy_write(phydev, regnum, val); + + spin_unlock(dp83640-extreg_lock); +} + +static int expired(struct rxts *rxts) +{ + return time_after(jiffies, rxts-tmo); +} + +static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts) +{ + u16 *seqid; + u8 *msgtype, *data = skb-data; + + switch (type) { + case PTP_CLASS_V1_IPV4: + msgtype = data + 42 + 32; + seqid = (u16 *)(data + 42 + 30); + break; + case
[PATCH 08/12] ptp: Added a brand new class driver for ptp clocks.
This patch adds an infrastructure for hardware clocks that implement IEEE 1588, the Precision Time Protocol (PTP). A class driver offers a registration method to particular hardware clock drivers. Each clock is exposed to user space as a character device with ioctls that allow tuning of the PTP clock. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- Documentation/ptp/ptp.txt| 95 +++ Documentation/ptp/testptp.c | 269 Documentation/ptp/testptp.mk | 33 +++ drivers/Kconfig |2 + drivers/Makefile |1 + drivers/ptp/Kconfig | 26 ++ drivers/ptp/Makefile |5 + drivers/ptp/ptp_clock.c | 514 ++ include/linux/Kbuild |1 + include/linux/ptp_clock.h| 79 ++ include/linux/ptp_clock_kernel.h | 137 ++ 11 files changed, 1162 insertions(+), 0 deletions(-) create mode 100644 Documentation/ptp/ptp.txt create mode 100644 Documentation/ptp/testptp.c create mode 100644 Documentation/ptp/testptp.mk create mode 100644 drivers/ptp/Kconfig create mode 100644 drivers/ptp/Makefile create mode 100644 drivers/ptp/ptp_clock.c create mode 100644 include/linux/ptp_clock.h create mode 100644 include/linux/ptp_clock_kernel.h diff --git a/Documentation/ptp/ptp.txt b/Documentation/ptp/ptp.txt new file mode 100644 index 000..46858b3 --- /dev/null +++ b/Documentation/ptp/ptp.txt @@ -0,0 +1,95 @@ + +* PTP infrastructure for Linux + + This patch set introduces support for IEEE 1588 PTP clocks in + Linux. Together with the SO_TIMESTAMPING socket options, this + presents a standardized method for developing PTP user space + programs, synchronizing Linux with external clocks, and using the + ancillary features of PTP hardware clocks. + + A new class driver exports a kernel interface for specific clock + drivers and a user space interface. The infrastructure supports a + complete set of PTP functionality. + + + Basic clock operations +- Set time +- Get time +- Shift the clock by a given offset atomically +- Adjust clock frequency + + + Ancillary clock features +- One short or periodic alarms, with signal delivery to user program +- Time stamp external events +- Period output signals configurable from user space +- Synchronization of the Linux system time via the PPS subsystem + +** PTP kernel API + + A PTP clock driver registers itself with the class driver. The + class driver handles all of the dealings with user space. The + author of a clock driver need only implement the details of + programming the clock hardware. The clock driver notifies the class + driver of asynchronous events (alarms and external time stamps) via + a simple message passing interface. + + The class driver supports multiple PTP clock drivers. In normal use + cases, only one PTP clock is needed. However, for testing and + development, it can be useful to have more than one clock in a + single system, in order to allow performance comparisons. + +** PTP user space API + + The class driver creates a character device for each registered PTP + clock. User space programs may control the clock using standardized + ioctls. A program may query, enable, configure, and disable the + ancillary clock features. User space can receive time stamped + events via blocking read() and poll(). One shot and periodic + signals may be configured via an ioctl API with semantics similar + to the POSIX timer_settime() system call. + + As an real life example, the following two patches for ptpd version + 1.0.0 demonstrate how the API works. + + https://sourceforge.net/tracker/?func=detailaid=2992845group_id=139814atid=744634 + + https://sourceforge.net/tracker/?func=detailaid=2992847group_id=139814atid=744634 + +** Writing clock drivers + + Clock drivers include include/linux/ptp_clock_kernel.h and register + themselves by presenting a 'struct ptp_clock_info' to the + registration method. Clock drivers must implement all of the + functions in the interface. If a clock does not offer a particular + ancillary feature, then the driver should just return -EOPNOTSUPP + from those functions. + + Drivers must ensure that all of the methods in interface are + reentrant. Since most hardware implementations treat the time value + as a 64 bit integer accessed as two 32 bit registers, drivers + should use spin_lock_irqsave/spin_unlock_irqrestore to protect + against concurrent access. This locking cannot be accomplished in + class driver, since the lock may also be needed by the clock + driver's interrupt service routine. + +** Supported hardware + + + Standard Linux system timer + - No special PTP features + - For use with software time stamping + + + Freescale eTSEC gianfar + - 2 Time stamp external triggers, programmable polarity (opt. interrupt) + -
[PATCH 09/12] ptp: Added a clock that uses the Linux system time.
This PTP clock simply uses the NTP time adjustment system calls. The driver can be used in systems that lack a special hardware PTP clock. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- drivers/ptp/Kconfig | 12 drivers/ptp/Makefile|1 + drivers/ptp/ptp_linux.c | 136 +++ kernel/time/ntp.c |2 + 4 files changed, 151 insertions(+), 0 deletions(-) create mode 100644 drivers/ptp/ptp_linux.c diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index c80a25b..9390d44 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -23,4 +23,16 @@ config PTP_1588_CLOCK To compile this driver as a module, choose M here: the module will be called ptp_clock. +config PTP_1588_CLOCK_LINUX + tristate Linux system timer as PTP clock + depends on PTP_1588_CLOCK + help + This driver adds support for using the standard Linux time + source as a PTP clock. This clock is only useful if your PTP + programs are using software time stamps for the PTP Ethernet + packets. + + To compile this driver as a module, choose M here: the module + will be called ptp_linux. + endmenu diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile index b86695c..1651d52 100644 --- a/drivers/ptp/Makefile +++ b/drivers/ptp/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_PTP_1588_CLOCK) += ptp_clock.o +obj-$(CONFIG_PTP_1588_CLOCK_LINUX) += ptp_linux.o diff --git a/drivers/ptp/ptp_linux.c b/drivers/ptp/ptp_linux.c new file mode 100644 index 000..f93ae0c --- /dev/null +++ b/drivers/ptp/ptp_linux.c @@ -0,0 +1,136 @@ +/* + * PTP 1588 clock using the Linux system clock + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include linux/device.h +#include linux/err.h +#include linux/hrtimer.h +#include linux/init.h +#include linux/kernel.h +#include linux/module.h +#include linux/timex.h + +#include linux/ptp_clock_kernel.h + +static struct ptp_clock *linux_clock; + +DEFINE_SPINLOCK(adjtime_lock); + +static int ptp_linux_adjfreq(void *priv, s32 delta) +{ + struct timex txc; + s64 tmp = delta; + int err; + txc.freq = div_s64(tmp16, 1000); + txc.modes = ADJ_FREQUENCY; + err = do_adjtimex(txc); + return err 0 ? err : 0; +} + +static int ptp_linux_adjtime(void *priv, struct timespec *ts) +{ + s64 delta; + ktime_t now; + struct timespec t2; + unsigned long flags; + int err; + + delta = 10LL * ts-tv_sec + ts-tv_nsec; + + spin_lock_irqsave(adjtime_lock, flags); + + now = ktime_get_real(); + + now = delta 0 ? ktime_sub_ns(now, -delta) : ktime_add_ns(now, delta); + + t2 = ktime_to_timespec(now); + + err = do_settimeofday(t2); + + spin_unlock_irqrestore(adjtime_lock, flags); + + return err; +} + +static int ptp_linux_gettime(void *priv, struct timespec *ts) +{ + getnstimeofday(ts); + return 0; +} + +static int ptp_linux_settime(void *priv, struct timespec *ts) +{ + return do_settimeofday(ts); +} + +static int ptp_linux_gettimer(void *priv, int index, struct itimerspec *ts) +{ + /* We do not offer any ancillary features at all. */ + return -EOPNOTSUPP; +} + +static int ptp_linux_settimer(void *p, int i, int abs, struct itimerspec *ts) +{ + /* We do not offer any ancillary features at all. */ + return -EOPNOTSUPP; +} + +static int ptp_linux_enable(void *priv, struct ptp_clock_request *rq, int on) +{ + /* We do not offer any ancillary features at all. */ + return -EOPNOTSUPP; +} + +static struct ptp_clock_info ptp_linux_caps = { + .owner = THIS_MODULE, + .name = Linux timer, + .max_adj= 512000, + .n_alarm= 0, + .n_ext_ts = 0, + .n_per_out = 0, + .pps= 0, + .priv = NULL, + .adjfreq= ptp_linux_adjfreq, + .adjtime= ptp_linux_adjtime, + .gettime= ptp_linux_gettime, + .settime= ptp_linux_settime, + .gettimer = ptp_linux_gettimer, + .settimer = ptp_linux_settimer, + .enable =
[PATCH 10/12] ptp: Added a clock that uses the eTSEC found on the MPC85xx.
The eTSEC includes a PTP clock with quite a few features. This patch adds support for the basic clock adjustment functions, plus two external time stamps and one alarm. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- Documentation/powerpc/dts-bindings/fsl/tsec.txt | 54 +++ arch/powerpc/boot/dts/mpc8313erdb.dts | 13 + arch/powerpc/boot/dts/p2020ds.dts | 13 + arch/powerpc/boot/dts/p2020rdb.dts | 13 + drivers/net/Makefile|1 + drivers/net/gianfar_ptp.c | 518 +++ drivers/net/gianfar_ptp_reg.h | 113 + drivers/ptp/Kconfig | 13 + 8 files changed, 738 insertions(+), 0 deletions(-) create mode 100644 drivers/net/gianfar_ptp.c create mode 100644 drivers/net/gianfar_ptp_reg.h diff --git a/Documentation/powerpc/dts-bindings/fsl/tsec.txt b/Documentation/powerpc/dts-bindings/fsl/tsec.txt index edb7ae1..14577e9 100644 --- a/Documentation/powerpc/dts-bindings/fsl/tsec.txt +++ b/Documentation/powerpc/dts-bindings/fsl/tsec.txt @@ -74,3 +74,57 @@ Example: interrupt-parent = mpic; phy-handle = phy0 }; + +* Gianfar PTP clock nodes + +General Properties: + + - compatible Should be fsl,etsec-ptp + - reg Offset and length of the register set for the device + - interrupts There should be at least two interrupts. Some devices + have as many as four PTP related interrupts. + +Clock Properties: + + - tclk_period Timer reference clock period in nanoseconds. + - tmr_prsc Prescaler, divides the output clock. + - tmr_add Frequency compensation value. + - cksel0= external clock, 1= eTSEC system clock, 3= RTC clock input. + Currently the driver only supports choice 1. + - tmr_fiper1 Fixed interval period pulse generator. + - tmr_fiper2 Fixed interval period pulse generator. + + These properties set the operational parameters for the PTP + clock. You must choose these carefully for the clock to work right. + Here is how to figure good values: + + TimerOsc = system clock MHz + tclk_period = desired clock period nanoseconds + NominalFreq = 1000 / tclk_period MHz + FreqDivRatio = TimerOsc / NominalFreq (must be greater that 1.0) + tmr_add = ceil(2^32 / FreqDivRatio) + OutputClock = NominalFreq / tmr_prsc MHz + PulseWidth = 1 / OutputClockmicroseconds + FiperFreq1 = desired frequency in Hz + FiperDiv1= 100 * OutputClock / FiperFreq1 + tmr_fiper1 = tmr_prsc * tclk_period * FiperDiv1 - tclk_period + + The calculation for tmr_fiper2 is the same as for tmr_fiper1. The + driver expects that tmr_fiper1 will be correctly set to produce a 1 + Pulse Per Second (PPS) signal, since this will be offered to the PPS + subsystem to synchronize the Linux clock. + +Example: + + ptp_cl...@24e00 { + compatible = fsl,etsec-ptp; + reg = 0x24E00 0xB0; + interrupts = 12 0x8 13 0x8; + interrupt-parent = ipic ; + tclk_period = 10; + tmr_prsc= 100; + tmr_add = 0x99A4; + cksel = 0x1; + tmr_fiper1 = 0x3B9AC9F6; + tmr_fiper2 = 0x00018696; + }; diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts index 183f2aa..0526384 100644 --- a/arch/powerpc/boot/dts/mpc8313erdb.dts +++ b/arch/powerpc/boot/dts/mpc8313erdb.dts @@ -208,6 +208,19 @@ sleep = pmc 0x0030; }; + ptp_cl...@24e00 { + compatible = fsl,etsec-ptp; + reg = 0x24E00 0xB0; + interrupts = 12 0x8 13 0x8; + interrupt-parent = ipic ; + tclk_period = 10; + tmr_prsc= 100; + tmr_add = 0x99A4; + cksel = 0x1; + tmr_fiper1 = 0x3B9AC9F6; + tmr_fiper2 = 0x00018696; + }; + enet0: ether...@24000 { #address-cells = 1; #size-cells = 1; diff --git a/arch/powerpc/boot/dts/p2020ds.dts b/arch/powerpc/boot/dts/p2020ds.dts index 1101914..ae5dc4d 100644 --- a/arch/powerpc/boot/dts/p2020ds.dts +++ b/arch/powerpc/boot/dts/p2020ds.dts @@ -336,6 +336,19 @@ phy_type = ulpi; }; + ptp_cl...@24e00 { + compatible = fsl,etsec-ptp; + reg = 0x24E00 0xB0; + interrupts = 68 2 69 2 70 2; + interrupt-parent = mpic ; + tclk_period = 5; + tmr_prsc = 200; + tmr_add =
[PATCH 11/12] ptp: Added a clock driver for the IXP46x.
This patch adds a driver for the hardware time stamping unit found on the IXP465. Only the basic clock operations are implemented. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h | 67 +++ drivers/net/arm/ixp4xx_eth.c | 194 + drivers/ptp/Kconfig | 13 ++ drivers/ptp/Makefile |1 + drivers/ptp/ptp_ixp46x.c | 231 + 5 files changed, 506 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h create mode 100644 drivers/ptp/ptp_ixp46x.c diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h b/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h new file mode 100644 index 000..7fb02b6 --- /dev/null +++ b/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h @@ -0,0 +1,67 @@ +/* + * PTP 1588 clock using the IXP46X + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _IXP46X_TS_H_ +#define _IXP46X_TS_H_ + +#define DEFAULT_ADDEND 0xF029 +#define TICKS_NS_SHIFT 4 + +struct ixp46x_channel_ctl { + u32 Ch_Control; /* 0x40 Time Synchronization Channel Control */ + u32 Ch_Event; /* 0x44 Time Synchronization Channel Event */ + u32 TxSnapLo; /* 0x48 Transmit Snapshot Low Register */ + u32 TxSnapHi; /* 0x4C Transmit Snapshot High Register */ + u32 RxSnapLo; /* 0x50 Receive Snapshot Low Register */ + u32 RxSnapHi; /* 0x54 Receive Snapshot High Register */ + u32 SrcUUIDLo; /* 0x58 Source UUID0 Low Register */ + u32 SrcUUIDHi; /* 0x5C Sequence Identifier/Source UUID0 High */ +}; + +struct ixp46x_ts_regs { + u32 Control; /* 0x00 Time Sync Control Register */ + u32 Event; /* 0x04 Time Sync Event Register */ + u32 Addend; /* 0x08 Time Sync Addend Register */ + u32 Accum; /* 0x0C Time Sync Accumulator Register */ + u32 Test;/* 0x10 Time Sync Test Register */ + u32 Unused; /* 0x14 */ + u32 RSysTime_Lo; /* 0x18 RawSystemTime_Low Register */ + u32 RSysTimeHi; /* 0x1C RawSystemTime_High Register */ + u32 SysTimeLo; /* 0x20 SystemTime_Low Register */ + u32 SysTimeHi; /* 0x24 SystemTime_High Register */ + u32 TrgtLo; /* 0x28 TargetTime_Low Register */ + u32 TrgtHi; /* 0x2C TargetTime_High Register */ + u32 ASMSLo; /* 0x30 Auxiliary Slave Mode Snapshot Low */ + u32 ASMSHi; /* 0x34 Auxiliary Slave Mode Snapshot High */ + u32 AMMSLo; /* 0x38 Auxiliary Master Mode Snapshot Low */ + u32 AMMSHi; /* 0x3C Auxiliary Master Mode Snapshot High */ + + struct ixp46x_channel_ctl channel[3]; +}; + +/* 0x40 Time Synchronization Channel Control Register Bits */ +#define MASTER_MODE (10) +#define TIMESTAMP_ALL (11) + +/* 0x44 Time Synchronization Channel Event Register Bits */ +#define TX_SNAPSHOT_LOCKED (10) +#define RX_SNAPSHOT_LOCKED (11) + +#endif diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 4f1cc71..2201960 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -30,9 +30,12 @@ #include linux/etherdevice.h #include linux/io.h #include linux/kernel.h +#include linux/net_tstamp.h #include linux/phy.h #include linux/platform_device.h +#include linux/ptp_classify.h #include linux/slab.h +#include mach/ixp46x_ts.h #include mach/npe.h #include mach/qmgr.h @@ -67,6 +70,14 @@ #define RXFREE_QUEUE(port_id) (NPE_ID(port_id) + 26) #define TXDONE_QUEUE 31 +#define PTP_SLAVE_MODE 1 +#define PTP_MASTER_MODE2 +#define PORT2CHANNEL(p)1 +/* + * PHYSICAL_ID(p-id) ? + * TODO - Figure out correct mapping. + */ + /* TX Control Registers */ #define TX_CNTRL0_TX_EN0x01 #define TX_CNTRL0_HALFDUPLEX 0x02 @@ -171,6 +182,8 @@ struct port { int id; /* logical port ID */ int speed, duplex; u8 firmware[4]; + int hwts_tx_en; + int hwts_rx_en; }; /* NPE message structure */ @@ -246,6 +259,170 @@ static int ports_open; static struct port *npe_port_tab[MAX_NPES]; static struct
[PATCH 12/12] ptp: Added a clock driver for the National Semiconductor PHYTER.
This patch adds support for the PTP clock found on the DP83640. Only the basic clock operations have been implemented. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- drivers/net/phy/Kconfig | 11 +++ drivers/net/phy/dp83640.c | 158 - 2 files changed, 168 insertions(+), 1 deletions(-) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 430cab1..507c68a 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -79,9 +79,20 @@ config NATIONAL_PHY config DP83640_PHY tristate Driver for the National Semiconductor DP83640 PHYTER + depends on PTP_1588_CLOCK + depends on NETWORK_PHY_TIMESTAMPING ---help--- Supports the DP83640 PHYTER with IEEE 1588 features. + This driver adds support for using the DP83640 as a PTP + clock. This clock is only useful if your PTP programs are + getting hardware time stamps on the PTP Ethernet packets + using the SO_TIMESTAMPING API. + + In order for this to work, your MAC driver must also + implement the the skb_tx_timetamp() and skb_rx_timetamp() + functions. + config STE10XP depends on PHYLIB tristate Driver for STMicroelectronics STe10Xp PHYs diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index a3217ea..21eadc3 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -26,6 +26,7 @@ #include linux/netdevice.h #include linux/phy.h #include linux/ptp_classify.h +#include linux/ptp_clock_kernel.h #include dp83640_reg.h @@ -45,10 +46,13 @@ struct rxts { }; struct dp83640_private { + struct phy_device *phydev; int hwts_tx_en; int hwts_rx_en; int layer; int version; + /* protects PTP_TDR register from concurrent access */ + spinlock_t ptp_tdr_lock; /* protects extended registers from concurrent access */ spinlock_t extreg_lock; int page; @@ -60,6 +64,9 @@ struct dp83640_private { /* globals */ +static struct ptp_clock *dp83640_clock; +DEFINE_SPINLOCK(clock_lock); /* protects the one and only dp83640_clock */ + static struct sock_filter ptp_filter[] = { PTP_FILTER }; @@ -99,6 +106,129 @@ static void ext_write(struct phy_device *phydev, int page, u32 regnum, u16 val) spin_unlock(dp83640-extreg_lock); } +static int tdr_write(struct dp83640_private *dp83640, +struct timespec *ts, u16 cmd) +{ + struct phy_device *phydev = dp83640-phydev; + + spin_lock(dp83640-ptp_tdr_lock); + + ext_write(phydev, PAGE4, PTP_TDR, ts-tv_nsec 0x);/* ns[15:0] */ + ext_write(phydev, PAGE4, PTP_TDR, ts-tv_nsec 16); /* ns[31:16] */ + ext_write(phydev, PAGE4, PTP_TDR, ts-tv_sec 0x); /* sec[15:0] */ + ext_write(phydev, PAGE4, PTP_TDR, ts-tv_sec 16);/* sec[31:16] */ + + ext_write(phydev, PAGE4, PTP_CTL, cmd); + + spin_unlock(dp83640-ptp_tdr_lock); + + return 0; +} + +/* ptp clock methods */ + +static int ptp_dp83640_adjfreq(void *priv, s32 ppb) +{ + struct dp83640_private *dp83640 = priv; + struct phy_device *phydev = dp83640-phydev; + u64 rate; + int neg_adj = 0; + u16 hi, lo; + + if (!ppb) + return 0; + + if (ppb 0) { + neg_adj = 1; + ppb = -ppb; + } + rate = ppb; + rate = 26; + rate = div_u64(rate, 1953125); + + hi = (rate 16) PTP_RATE_HI_MASK; + if (neg_adj) + hi |= PTP_RATE_DIR; + + lo = rate 0x; + + ext_write(phydev, PAGE4, PTP_RATEH, hi); + ext_write(phydev, PAGE4, PTP_RATEL, lo); + + return 0; +} + +static int ptp_dp83640_adjtime(void *priv, struct timespec *ts) +{ + return tdr_write(priv, ts, PTP_STEP_CLK); +} + +static int ptp_dp83640_gettime(void *priv, struct timespec *ts) +{ + struct dp83640_private *dp83640 = priv; + struct phy_device *phydev = dp83640-phydev; + unsigned int val[4]; + + spin_lock(dp83640-ptp_tdr_lock); + + ext_write(phydev, PAGE4, PTP_CTL, PTP_RD_CLK); + + val[0] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[15:0] */ + val[1] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[31:16] */ + val[2] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[15:0] */ + val[3] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[31:16] */ + + spin_unlock(dp83640-ptp_tdr_lock); + + ts-tv_nsec = val[0] | (val[1] 16); + ts-tv_sec = val[2] | (val[3] 16); + + return 0; +} + +static int ptp_dp83640_settime(void *priv, struct timespec *ts) +{ + return tdr_write(priv, ts, PTP_LOAD_CLK); +} + +static int ptp_dp83640_gettimer(void *priv, int index, struct itimerspec *ts) +{ + /* We do not (yet) offer any ancillary features. */ + return -EOPNOTSUPP; +} + +static int ptp_dp83640_settimer(void *p, int i, int abs, struct itimerspec
Re: [PATCH 5/5] of/address: restrict 'no-ranges' kludge to powerpc
Certain Apple machines don't use the ranges property correctly, but the workaround should not be applied on other architectures. This patch disables the workaround for non-powerpc architectures. I'm half tempted to add it to the quirk list (which should really be made generic) so I can disable it on more 'modern' powerpc as well. Oh please oh please oh please yes do. OTOH, it would be even better to just fix up the device tree in the early platform code. Quirks are for broken hardware; software, we can fix. Segher ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 02/12] phylib: do not filter phy_mii_ioctl()
On Tue, Jun 15, 2010 at 10:07 AM, Richard Cochran richardcoch...@gmail.com wrote: Two maverick drivers filter the ioctl commands passed to phy_mii_ioctl(). This is unnecessary since phylib will check the command in any case. Signed-off-by: Richard Cochran richard.coch...@omicron.at At a glance, looks okay to me. --- drivers/net/cpmac.c | 5 + drivers/net/stmmac/stmmac_main.c | 22 -- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index d4c5ca4..0e47ca1 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -846,11 +846,8 @@ static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EINVAL; if (!priv-phy) return -EINVAL; - if ((cmd == SIOCGMIIPHY) || (cmd == SIOCGMIIREG) || - (cmd == SIOCSMIIREG)) - return phy_mii_ioctl(priv-phy, ifr, cmd); - return -EOPNOTSUPP; + return phy_mii_ioctl(priv-phy, ifr, cmd); } static int cpmac_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 6af7471..acf0616 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -1437,24 +1437,18 @@ static void stmmac_poll_controller(struct net_device *dev) static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct stmmac_priv *priv = netdev_priv(dev); - int ret = -EOPNOTSUPP; + int ret; if (!netif_running(dev)) return -EINVAL; - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - if (!priv-phydev) - return -EINVAL; - - spin_lock(priv-lock); - ret = phy_mii_ioctl(priv-phydev, rq, cmd); - spin_unlock(priv-lock); - default: - break; - } + if (!priv-phydev) + return -EINVAL; + + spin_lock(priv-lock); + ret = phy_mii_ioctl(priv-phydev, rq, cmd); + spin_unlock(priv-lock); + return ret; } -- 1.6.3.3 ___ linux-arm-kernel mailing list linux-arm-ker...@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel -- Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 03/12] phylib: add a driver method for the SIOCSHWTSTAMP ioctl.
On Tue, Jun 15, 2010 at 10:08 AM, Richard Cochran richardcoch...@gmail.com wrote: This patch adds a phy driver method for configuring hardware time stamping. Drivers may optionally implement this function. Signed-off-by: Richard Cochran richard.coch...@omicron.at Adding an ioctl to the userspace ABI. Make sure you cc: linux-kernel on the next spin of this series. g. --- drivers/net/phy/phy.c | 5 + include/linux/phy.h | 3 +++ 2 files changed, 8 insertions(+), 0 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index bd88d81..5130db8 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -361,6 +361,11 @@ int phy_mii_ioctl(struct phy_device *phydev, } break; + case SIOCSHWTSTAMP: + if (phydev-drv-hwtstamp) + return phydev-drv-hwtstamp(phydev, ifr); + /* fall through */ + default: return -EOPNOTSUPP; } diff --git a/include/linux/phy.h b/include/linux/phy.h index d63736a..a5e9df1 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -402,6 +402,9 @@ struct phy_driver { /* Clears up any memory if needed */ void (*remove)(struct phy_device *phydev); + /* Handles SIOCSHWTSTAMP ioctl for hardware time stamping. */ + int (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr); + struct device_driver driver; }; #define to_phy_driver(d) container_of(d, struct phy_driver, driver) -- 1.6.3.3 ___ linux-arm-kernel mailing list linux-arm-ker...@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel -- Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 03/12] phylib: add a driver method for the SIOCSHWTSTAMP ioctl.
On Tue, Jun 15, 2010 at 10:27:59AM -0600, Grant Likely wrote: On Tue, Jun 15, 2010 at 10:08 AM, Richard Cochran richardcoch...@gmail.com wrote: This patch adds a phy driver method for configuring hardware time stamping. Drivers may optionally implement this function. Signed-off-by: Richard Cochran richard.coch...@omicron.at Adding an ioctl to the userspace ABI. Make sure you cc: linux-kernel on the next spin of this series. Not sure what you mean. SIOCSHWTSTAMP is a standard socket option as of 2.6.30. The patch just makes it possible for PHY drivers to implement this option. Richard ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 04/12] phylib: add a way to make PHY time stamps possible.
On Tue, Jun 15, 2010 at 10:08 AM, Richard Cochran richardcoch...@gmail.com wrote: This patch adds a new networking option to allow hardware time stamps from PHY devices. Using PHY time stamps will still require adding two inline function calls to each MAC driver. The CONFIG option makes these calls safe to add, since the calls become NOOPs when the option is disabled. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- include/linux/phy.h | 4 include/linux/skbuff.h | 32 net/Kconfig | 11 +++ 3 files changed, 47 insertions(+), 0 deletions(-) [...] diff --git a/net/Kconfig b/net/Kconfig index 0d68b40..3fa7ae3 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -86,6 +86,17 @@ config NETWORK_SECMARK to nfmark, but designated for security purposes. If you are unsure how to answer this question, answer N. +config NETWORK_PHY_TIMESTAMPING + bool Timestamping in PHY devices + depends on EXPERIMENTAL + help + This allows timestamping of network packets by PHYs with + hardware timestamping capabilities. This option adds some + overhead in the transmit and receive paths. Note that this + option also requires support in the MAC driver. Some overhead? At a brief glance of the series it looks like it could add a lot of overhead, but I'm not fully clear on what the full process is. Can you describe how the hardware timestamping works? I could use an overview of what the kernel has to do. g. -- Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 05/12] phylib: Allow reading and writing a mii bus from atomic context.
On Tue, Jun 15, 2010 at 10:08 AM, Richard Cochran richardcoch...@gmail.com wrote: In order to support hardware time stamping from a PHY, it is necessary to read from the PHY while running in_interrupt(). This patch allows a mii bus to operate in an atomic context. An mii_bus driver may declare itself capable for this mode. Drivers which do not do this will remain with the default that bus operations may sleep. Signed-off-by: Richard Cochran richard.coch...@omicron.at Last I checked, the MDIO bus is very slow. Is this really a good idea? How much latency does MDIO access have on the hardware you are working with? I also don't like the idea of taking a spin lock during MDIO operations, and the dual locking mode in the core code. I'd rather see separate atomic context hooks that doesn't obtain the mutex under the assumption that the caller has already done so. If the bus doesn't support atomic access, then it won't implement the hooks and the core code should return an error. I've cc'd Thomas Gleixner. He might have a better idea about how to implement what you're trying to do. g. --- drivers/net/phy/mdio_bus.c | 35 --- include/linux/phy.h | 13 +++-- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 6a6b819..441be7d 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -36,6 +36,22 @@ #include asm/irq.h #include asm/uaccess.h +static inline void mdiobus_lock(struct mii_bus *bus) +{ + if (MDIOBUS_SLEEPS_RW == bus-locktype) + mutex_lock(bus-mdio_lock.m); + else + spin_lock(bus-mdio_lock.s); +} + +static inline void mdiobus_unlock(struct mii_bus *bus) +{ + if (MDIOBUS_SLEEPS_RW == bus-locktype) + mutex_unlock(bus-mdio_lock.m); + else + spin_unlock(bus-mdio_lock.s); +} + /** * mdiobus_alloc - allocate a mii_bus structure * @@ -107,7 +123,10 @@ int mdiobus_register(struct mii_bus *bus) return -EINVAL; } - mutex_init(bus-mdio_lock); + if (MDIOBUS_SLEEPS_RW == bus-locktype) + mutex_init(bus-mdio_lock.m); + else + spin_lock_init(bus-mdio_lock.s); if (bus-reset) bus-reset(bus); @@ -212,11 +231,12 @@ int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) { int retval; - BUG_ON(in_interrupt()); + if (MDIOBUS_SLEEPS_RW == bus-locktype) + BUG_ON(in_interrupt()); - mutex_lock(bus-mdio_lock); + mdiobus_lock(bus); retval = bus-read(bus, addr, regnum); - mutex_unlock(bus-mdio_lock); + mdiobus_unlock(bus); return retval; } @@ -237,11 +257,12 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) { int err; - BUG_ON(in_interrupt()); + if (MDIOBUS_SLEEPS_RW == bus-locktype) + BUG_ON(in_interrupt()); - mutex_lock(bus-mdio_lock); + mdiobus_lock(bus); err = bus-write(bus, addr, regnum, val); - mutex_unlock(bus-mdio_lock); + mdiobus_unlock(bus); return err; } diff --git a/include/linux/phy.h b/include/linux/phy.h index 7a8caac..352b030 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -98,11 +98,20 @@ struct mii_bus { int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val); int (*reset)(struct mii_bus *bus); + /* Indicates whether bus may be used from an atomic context. */ + enum { + MDIOBUS_SLEEPS_RW, + MDIOBUS_ATOMIC_RW + } locktype; + /* - * A lock to ensure that only one thing can read/write + * A lock or mutex to ensure that only one thing can read/write * the MDIO bus at a time */ - struct mutex mdio_lock; + union { + struct mutex m; + spinlock_t s; + } mdio_lock; struct device *parent; enum { -- 1.6.3.3 ___ linux-arm-kernel mailing list linux-arm-ker...@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel -- Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 03/12] phylib: add a driver method for the SIOCSHWTSTAMP ioctl.
On Tue, Jun 15, 2010 at 10:34 AM, Richard Cochran richardcoch...@gmail.com wrote: On Tue, Jun 15, 2010 at 10:27:59AM -0600, Grant Likely wrote: On Tue, Jun 15, 2010 at 10:08 AM, Richard Cochran richardcoch...@gmail.com wrote: This patch adds a phy driver method for configuring hardware time stamping. Drivers may optionally implement this function. Signed-off-by: Richard Cochran richard.coch...@omicron.at Adding an ioctl to the userspace ABI. Make sure you cc: linux-kernel on the next spin of this series. Not sure what you mean. SIOCSHWTSTAMP is a standard socket option as of 2.6.30. The patch just makes it possible for PHY drivers to implement this option. Ah, sorry. I didn't go check that first. g. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 03/12] phylib: add a driver method for the SIOCSHWTSTAMP ioctl.
On Tue, Jun 15, 2010 at 10:49 AM, Grant Likely grant.lik...@secretlab.ca wrote: On Tue, Jun 15, 2010 at 10:34 AM, Richard Cochran richardcoch...@gmail.com wrote: On Tue, Jun 15, 2010 at 10:27:59AM -0600, Grant Likely wrote: On Tue, Jun 15, 2010 at 10:08 AM, Richard Cochran richardcoch...@gmail.com wrote: This patch adds a phy driver method for configuring hardware time stamping. Drivers may optionally implement this function. Signed-off-by: Richard Cochran richard.coch...@omicron.at Adding an ioctl to the userspace ABI. Make sure you cc: linux-kernel on the next spin of this series. Not sure what you mean. SIOCSHWTSTAMP is a standard socket option as of 2.6.30. The patch just makes it possible for PHY drivers to implement this option. Ah, sorry. I didn't go check that first. Although, now that I'm looking through the PTP patches, you *definitely* should post this series to the lkml. It has implications beyond ppc and arm. g. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 08/12] ptp: Added a brand new class driver for ptp clocks.
On Tue, Jun 15, 2010 at 10:09 AM, Richard Cochran richardcoch...@gmail.com wrote: This patch adds an infrastructure for hardware clocks that implement IEEE 1588, the Precision Time Protocol (PTP). A class driver offers a registration method to particular hardware clock drivers. Each clock is exposed to user space as a character device with ioctls that allow tuning of the PTP clock. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- Documentation/ptp/ptp.txt | 95 +++ Documentation/ptp/testptp.c | 269 Documentation/ptp/testptp.mk | 33 +++ drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/ptp/Kconfig | 26 ++ drivers/ptp/Makefile | 5 + drivers/ptp/ptp_clock.c | 514 ++ include/linux/Kbuild | 1 + include/linux/ptp_clock.h | 79 ++ include/linux/ptp_clock_kernel.h | 137 ++ 11 files changed, 1162 insertions(+), 0 deletions(-) create mode 100644 Documentation/ptp/ptp.txt create mode 100644 Documentation/ptp/testptp.c create mode 100644 Documentation/ptp/testptp.mk create mode 100644 drivers/ptp/Kconfig create mode 100644 drivers/ptp/Makefile create mode 100644 drivers/ptp/ptp_clock.c create mode 100644 include/linux/ptp_clock.h create mode 100644 include/linux/ptp_clock_kernel.h diff --git a/Documentation/ptp/ptp.txt b/Documentation/ptp/ptp.txt new file mode 100644 index 000..46858b3 --- /dev/null +++ b/Documentation/ptp/ptp.txt @@ -0,0 +1,95 @@ + +* PTP infrastructure for Linux + + This patch set introduces support for IEEE 1588 PTP clocks in + Linux. Together with the SO_TIMESTAMPING socket options, this + presents a standardized method for developing PTP user space + programs, synchronizing Linux with external clocks, and using the + ancillary features of PTP hardware clocks. + + A new class driver exports a kernel interface for specific clock + drivers and a user space interface. The infrastructure supports a + complete set of PTP functionality. + + + Basic clock operations + - Set time + - Get time + - Shift the clock by a given offset atomically + - Adjust clock frequency + + + Ancillary clock features + - One short or periodic alarms, with signal delivery to user program + - Time stamp external events + - Period output signals configurable from user space + - Synchronization of the Linux system time via the PPS subsystem + +** PTP kernel API + + A PTP clock driver registers itself with the class driver. The + class driver handles all of the dealings with user space. The + author of a clock driver need only implement the details of + programming the clock hardware. The clock driver notifies the class + driver of asynchronous events (alarms and external time stamps) via + a simple message passing interface. + + The class driver supports multiple PTP clock drivers. In normal use + cases, only one PTP clock is needed. However, for testing and + development, it can be useful to have more than one clock in a + single system, in order to allow performance comparisons. + +** PTP user space API + + The class driver creates a character device for each registered PTP + clock. User space programs may control the clock using standardized + ioctls. A program may query, enable, configure, and disable the + ancillary clock features. User space can receive time stamped + events via blocking read() and poll(). One shot and periodic + signals may be configured via an ioctl API with semantics similar + to the POSIX timer_settime() system call. + + As an real life example, the following two patches for ptpd version + 1.0.0 demonstrate how the API works. + + https://sourceforge.net/tracker/?func=detailaid=2992845group_id=139814atid=744634 + + https://sourceforge.net/tracker/?func=detailaid=2992847group_id=139814atid=744634 Question from an ignorant reviewer: Why a new interface instead of working with the existing high resolution timers infrastructure? g. + +** Writing clock drivers + + Clock drivers include include/linux/ptp_clock_kernel.h and register + themselves by presenting a 'struct ptp_clock_info' to the + registration method. Clock drivers must implement all of the + functions in the interface. If a clock does not offer a particular + ancillary feature, then the driver should just return -EOPNOTSUPP + from those functions. + + Drivers must ensure that all of the methods in interface are + reentrant. Since most hardware implementations treat the time value + as a 64 bit integer accessed as two 32 bit registers, drivers + should use spin_lock_irqsave/spin_unlock_irqrestore to protect + against concurrent access. This locking cannot be accomplished in + class driver, since the
Re: [PATCH 05/12] phylib: Allow reading and writing a mii bus from atomic context.
On Tue, Jun 15, 2010 at 10:43:08AM -0600, Grant Likely wrote: On Tue, Jun 15, 2010 at 10:08 AM, Richard Cochran richardcoch...@gmail.com wrote: In order to support hardware time stamping from a PHY, it is necessary to read from the PHY while running in_interrupt(). This patch allows a mii bus to operate in an atomic context. An mii_bus driver may declare itself capable for this mode. Drivers which do not do this will remain with the default that bus operations may sleep. Signed-off-by: Richard Cochran richard.coch...@omicron.at Last I checked, the MDIO bus is very slow. Is this really a good idea? How much latency does MDIO access have on the hardware you are working with? Yes, MDIO access is slow, and it can vary (eg bit banging implementations). It clear that getting PHY timestamps is costly, but for applications that want PTP synchronization, one is willing to pay the price. I also don't like the idea of taking a spin lock during MDIO operations, and the dual locking mode in the core code. Originally, the phylib used a spinlock for this. It was replaced with a mutex in 35b5f6b1a82b5c586e0b24c711dc6ba944e88ef1 in order to accommodate mdio busses that may need to sleep. So, keeping the option to use a spinlock is similar to the previous implementation. I'd rather see separate atomic context hooks that doesn't obtain the mutex under the assumption that the caller has already done so. If the bus doesn't support atomic access, then it won't implement the hooks and the core code should return an error. I've cc'd Thomas Gleixner. He might have a better idea about how to implement what you're trying to do. Okay, I'm open to suggestions... Thanks, Richard ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 10/12] ptp: Added a clock that uses the eTSEC found on the MPC85xx.
On Tue, Jun 15, 2010 at 10:10 AM, Richard Cochran richardcoch...@gmail.com wrote: The eTSEC includes a PTP clock with quite a few features. This patch adds support for the basic clock adjustment functions, plus two external time stamps and one alarm. Signed-off-by: Richard Cochran richard.coch...@omicron.at Hi Richard, comments below... --- Documentation/powerpc/dts-bindings/fsl/tsec.txt | 54 +++ arch/powerpc/boot/dts/mpc8313erdb.dts | 13 + arch/powerpc/boot/dts/p2020ds.dts | 13 + arch/powerpc/boot/dts/p2020rdb.dts | 13 + drivers/net/Makefile | 1 + drivers/net/gianfar_ptp.c | 518 +++ drivers/net/gianfar_ptp_reg.h | 113 + Is this header file used by anything other than gianfar_ptp.c? If not, then roll the two files together. drivers/ptp/Kconfig | 13 + 8 files changed, 738 insertions(+), 0 deletions(-) create mode 100644 drivers/net/gianfar_ptp.c create mode 100644 drivers/net/gianfar_ptp_reg.h diff --git a/Documentation/powerpc/dts-bindings/fsl/tsec.txt b/Documentation/powerpc/dts-bindings/fsl/tsec.txt index edb7ae1..14577e9 100644 --- a/Documentation/powerpc/dts-bindings/fsl/tsec.txt +++ b/Documentation/powerpc/dts-bindings/fsl/tsec.txt @@ -74,3 +74,57 @@ Example: interrupt-parent = mpic; phy-handle = phy0 }; + +* Gianfar PTP clock nodes + +General Properties: + + - compatible Should be fsl,etsec-ptp + - reg Offset and length of the register set for the device + - interrupts There should be at least two interrupts. Some devices + have as many as four PTP related interrupts. + +Clock Properties: + + - tclk_period Timer reference clock period in nanoseconds. + - tmr_prsc Prescaler, divides the output clock. + - tmr_add Frequency compensation value. Use dash ('-') not underscore ('_') in property names. + - cksel 0= external clock, 1= eTSEC system clock, 3= RTC clock input. + Currently the driver only supports choice 1. If you encode this value as a string, then it will be friendly for humans too. + - tmr_fiper1 Fixed interval period pulse generator. + - tmr_fiper2 Fixed interval period pulse generator. I could use more explication here. Is this a divider value? Computers are good at making calculations, and the driver can obtain the clock frequency supplied to the device. It may be more useful to specify here the desired frequency rather than the divider. Certainly more human-friendly too. + + These properties set the operational parameters for the PTP + clock. You must choose these carefully for the clock to work right. + Here is how to figure good values: + + TimerOsc = system clock MHz + tclk_period = desired clock period nanoseconds + NominalFreq = 1000 / tclk_period MHz + FreqDivRatio = TimerOsc / NominalFreq (must be greater that 1.0) + tmr_add = ceil(2^32 / FreqDivRatio) + OutputClock = NominalFreq / tmr_prsc MHz + PulseWidth = 1 / OutputClock microseconds + FiperFreq1 = desired frequency in Hz + FiperDiv1 = 100 * OutputClock / FiperFreq1 + tmr_fiper1 = tmr_prsc * tclk_period * FiperDiv1 - tclk_period + + The calculation for tmr_fiper2 is the same as for tmr_fiper1. The + driver expects that tmr_fiper1 will be correctly set to produce a 1 + Pulse Per Second (PPS) signal, since this will be offered to the PPS + subsystem to synchronize the Linux clock. + +Example: + + ptp_cl...@24e00 { + compatible = fsl,etsec-ptp; + reg = 0x24E00 0xB0; + interrupts = 12 0x8 13 0x8; + interrupt-parent = ipic ; + tclk_period = 10; + tmr_prsc = 100; + tmr_add = 0x99A4; + cksel = 0x1; + tmr_fiper1 = 0x3B9AC9F6; + tmr_fiper2 = 0x00018696; + }; diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts index 183f2aa..0526384 100644 --- a/arch/powerpc/boot/dts/mpc8313erdb.dts +++ b/arch/powerpc/boot/dts/mpc8313erdb.dts @@ -208,6 +208,19 @@ sleep = pmc 0x0030; }; + ptp_cl...@24e00 { + compatible = fsl,etsec-ptp; + reg = 0x24E00 0xB0; + interrupts = 12 0x8 13 0x8; + interrupt-parent = ipic ; + tclk_period = 10; + tmr_prsc = 100; + tmr_add = 0x99A4; + cksel = 0x1; + tmr_fiper1 = 0x3B9AC9F6; + tmr_fiper2 = 0x00018696; + }; +
Re: [PATCH 05/12] phylib: Allow reading and writing a mii bus from atomic context.
On Tue, Jun 15, 2010 at 11:08 AM, Richard Cochran richardcoch...@gmail.com wrote: On Tue, Jun 15, 2010 at 10:43:08AM -0600, Grant Likely wrote: On Tue, Jun 15, 2010 at 10:08 AM, Richard Cochran richardcoch...@gmail.com wrote: In order to support hardware time stamping from a PHY, it is necessary to read from the PHY while running in_interrupt(). This patch allows a mii bus to operate in an atomic context. An mii_bus driver may declare itself capable for this mode. Drivers which do not do this will remain with the default that bus operations may sleep. Signed-off-by: Richard Cochran richard.coch...@omicron.at Last I checked, the MDIO bus is very slow. Is this really a good idea? How much latency does MDIO access have on the hardware you are working with? Yes, MDIO access is slow, and it can vary (eg bit banging implementations). It clear that getting PHY timestamps is costly, but for applications that want PTP synchronization, one is willing to pay the price. I also don't like the idea of taking a spin lock during MDIO operations, and the dual locking mode in the core code. Originally, the phylib used a spinlock for this. It was replaced with a mutex in 35b5f6b1a82b5c586e0b24c711dc6ba944e88ef1 in order to accommodate mdio busses that may need to sleep. So, keeping the option to use a spinlock is similar to the previous implementation. That's right, and I fully agree with that change. To me, going back to allowing spin locks is a regression because it adds a new source of scheduling latency. Using a mutex forces users to take into account the slow nature of MDIO access. For existing callers, this isn't a problem because they already are designed for this characteristic. A new user which depends on atomic access should use a different API which doesn't take the lock with the understanding that it is may return a failure if it doesn't support it or if it cannot perform the operation atomically. That still leaves the troubling MDIO induced latency issue. g. -- Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 11/12] ptp: Added a clock driver for the IXP46x.
On Tue, Jun 15, 2010 at 10:10 AM, Richard Cochran richardcoch...@gmail.com wrote: This patch adds a driver for the hardware time stamping unit found on the IXP465. Only the basic clock operations are implemented. Signed-off-by: Richard Cochran richard.coch...@omicron.at Hi Richard, Comments below... --- arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h | 67 +++ drivers/net/arm/ixp4xx_eth.c | 194 + drivers/ptp/Kconfig | 13 ++ drivers/ptp/Makefile | 1 + drivers/ptp/ptp_ixp46x.c | 231 + 5 files changed, 506 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h create mode 100644 drivers/ptp/ptp_ixp46x.c diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h b/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h new file mode 100644 index 000..7fb02b6 --- /dev/null +++ b/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h @@ -0,0 +1,67 @@ +/* + * PTP 1588 clock using the IXP46X + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _IXP46X_TS_H_ +#define _IXP46X_TS_H_ + +#define DEFAULT_ADDEND 0xF029 +#define TICKS_NS_SHIFT 4 + +struct ixp46x_channel_ctl { + u32 Ch_Control; /* 0x40 Time Synchronization Channel Control */ + u32 Ch_Event; /* 0x44 Time Synchronization Channel Event */ + u32 TxSnapLo; /* 0x48 Transmit Snapshot Low Register */ + u32 TxSnapHi; /* 0x4C Transmit Snapshot High Register */ + u32 RxSnapLo; /* 0x50 Receive Snapshot Low Register */ + u32 RxSnapHi; /* 0x54 Receive Snapshot High Register */ + u32 SrcUUIDLo; /* 0x58 Source UUID0 Low Register */ + u32 SrcUUIDHi; /* 0x5C Sequence Identifier/Source UUID0 High */ +}; Nitpick. We use all lower case names for structures in Linux. + +struct ixp46x_ts_regs { + u32 Control; /* 0x00 Time Sync Control Register */ + u32 Event; /* 0x04 Time Sync Event Register */ + u32 Addend; /* 0x08 Time Sync Addend Register */ + u32 Accum; /* 0x0C Time Sync Accumulator Register */ + u32 Test; /* 0x10 Time Sync Test Register */ + u32 Unused; /* 0x14 */ + u32 RSysTime_Lo; /* 0x18 RawSystemTime_Low Register */ + u32 RSysTimeHi; /* 0x1C RawSystemTime_High Register */ + u32 SysTimeLo; /* 0x20 SystemTime_Low Register */ + u32 SysTimeHi; /* 0x24 SystemTime_High Register */ + u32 TrgtLo; /* 0x28 TargetTime_Low Register */ + u32 TrgtHi; /* 0x2C TargetTime_High Register */ + u32 ASMSLo; /* 0x30 Auxiliary Slave Mode Snapshot Low */ + u32 ASMSHi; /* 0x34 Auxiliary Slave Mode Snapshot High */ + u32 AMMSLo; /* 0x38 Auxiliary Master Mode Snapshot Low */ + u32 AMMSHi; /* 0x3C Auxiliary Master Mode Snapshot High */ + + struct ixp46x_channel_ctl channel[3]; +}; + +/* 0x40 Time Synchronization Channel Control Register Bits */ +#define MASTER_MODE (10) +#define TIMESTAMP_ALL (11) + +/* 0x44 Time Synchronization Channel Event Register Bits */ +#define TX_SNAPSHOT_LOCKED (10) +#define RX_SNAPSHOT_LOCKED (11) + +#endif diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 4f1cc71..2201960 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -30,9 +30,12 @@ #include linux/etherdevice.h #include linux/io.h #include linux/kernel.h +#include linux/net_tstamp.h #include linux/phy.h #include linux/platform_device.h +#include linux/ptp_classify.h #include linux/slab.h +#include mach/ixp46x_ts.h #include mach/npe.h #include mach/qmgr.h @@ -67,6 +70,14 @@ #define RXFREE_QUEUE(port_id) (NPE_ID(port_id) + 26) #define TXDONE_QUEUE 31 +#define PTP_SLAVE_MODE 1 +#define PTP_MASTER_MODE 2 +#define PORT2CHANNEL(p) 1 +/* + * PHYSICAL_ID(p-id) ? + * TODO - Figure out correct mapping. + */ + /* TX Control Registers */ #define TX_CNTRL0_TX_EN 0x01 #define TX_CNTRL0_HALFDUPLEX 0x02 @@ -171,6 +182,8 @@ struct port {
Re: [PATCH 12/12] ptp: Added a clock driver for the National Semiconductor PHYTER.
On Tue, Jun 15, 2010 at 10:10 AM, Richard Cochran richardcoch...@gmail.com wrote: This patch adds support for the PTP clock found on the DP83640. Only the basic clock operations have been implemented. Signed-off-by: Richard Cochran richard.coch...@omicron.at --- drivers/net/phy/Kconfig | 11 +++ drivers/net/phy/dp83640.c | 158 - 2 files changed, 168 insertions(+), 1 deletions(-) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 430cab1..507c68a 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -79,9 +79,20 @@ config NATIONAL_PHY config DP83640_PHY tristate Driver for the National Semiconductor DP83640 PHYTER + depends on PTP_1588_CLOCK + depends on NETWORK_PHY_TIMESTAMPING Won't this break things for existing DP83640 users? ---help--- Supports the DP83640 PHYTER with IEEE 1588 features. + This driver adds support for using the DP83640 as a PTP + clock. This clock is only useful if your PTP programs are + getting hardware time stamps on the PTP Ethernet packets + using the SO_TIMESTAMPING API. + + In order for this to work, your MAC driver must also + implement the the skb_tx_timetamp() and skb_rx_timetamp() + functions. + config STE10XP depends on PHYLIB tristate Driver for STMicroelectronics STe10Xp PHYs diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index a3217ea..21eadc3 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -26,6 +26,7 @@ #include linux/netdevice.h #include linux/phy.h #include linux/ptp_classify.h +#include linux/ptp_clock_kernel.h #include dp83640_reg.h @@ -45,10 +46,13 @@ struct rxts { }; struct dp83640_private { + struct phy_device *phydev; int hwts_tx_en; int hwts_rx_en; int layer; int version; + /* protects PTP_TDR register from concurrent access */ + spinlock_t ptp_tdr_lock; /* protects extended registers from concurrent access */ spinlock_t extreg_lock; int page; @@ -60,6 +64,9 @@ struct dp83640_private { /* globals */ +static struct ptp_clock *dp83640_clock; +DEFINE_SPINLOCK(clock_lock); /* protects the one and only dp83640_clock */ Why only one? Is it not possible to have 2 of these PHYs in a system? + static struct sock_filter ptp_filter[] = { PTP_FILTER }; @@ -99,6 +106,129 @@ static void ext_write(struct phy_device *phydev, int page, u32 regnum, u16 val) spin_unlock(dp83640-extreg_lock); } +static int tdr_write(struct dp83640_private *dp83640, + struct timespec *ts, u16 cmd) +{ + struct phy_device *phydev = dp83640-phydev; + + spin_lock(dp83640-ptp_tdr_lock); + + ext_write(phydev, PAGE4, PTP_TDR, ts-tv_nsec 0x);/* ns[15:0] */ + ext_write(phydev, PAGE4, PTP_TDR, ts-tv_nsec 16); /* ns[31:16] */ + ext_write(phydev, PAGE4, PTP_TDR, ts-tv_sec 0x); /* sec[15:0] */ + ext_write(phydev, PAGE4, PTP_TDR, ts-tv_sec 16); /* sec[31:16] */ + + ext_write(phydev, PAGE4, PTP_CTL, cmd); + + spin_unlock(dp83640-ptp_tdr_lock); + + return 0; +} + +/* ptp clock methods */ + +static int ptp_dp83640_adjfreq(void *priv, s32 ppb) +{ + struct dp83640_private *dp83640 = priv; + struct phy_device *phydev = dp83640-phydev; + u64 rate; + int neg_adj = 0; + u16 hi, lo; + + if (!ppb) + return 0; + + if (ppb 0) { + neg_adj = 1; + ppb = -ppb; + } + rate = ppb; + rate = 26; + rate = div_u64(rate, 1953125); + + hi = (rate 16) PTP_RATE_HI_MASK; + if (neg_adj) + hi |= PTP_RATE_DIR; + + lo = rate 0x; + + ext_write(phydev, PAGE4, PTP_RATEH, hi); + ext_write(phydev, PAGE4, PTP_RATEL, lo); + + return 0; +} + +static int ptp_dp83640_adjtime(void *priv, struct timespec *ts) +{ + return tdr_write(priv, ts, PTP_STEP_CLK); +} + +static int ptp_dp83640_gettime(void *priv, struct timespec *ts) +{ + struct dp83640_private *dp83640 = priv; + struct phy_device *phydev = dp83640-phydev; + unsigned int val[4]; + + spin_lock(dp83640-ptp_tdr_lock); + + ext_write(phydev, PAGE4, PTP_CTL, PTP_RD_CLK); + + val[0] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[15:0] */ + val[1] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[31:16] */ + val[2] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[15:0] */ + val[3] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[31:16] */ + + spin_unlock(dp83640-ptp_tdr_lock); + + ts-tv_nsec = val[0] | (val[1] 16); + ts-tv_sec = val[2] | (val[3] 16); + + return 0; +} + +static int
Re: [PATCH 08/12] ptp: Added a brand new class driver for ptp clocks.
On Tue, Jun 15, 2010 at 10:09 AM, Richard Cochran richardcoch...@gmail.com wrote: This patch adds an infrastructure for hardware clocks that implement IEEE 1588, the Precision Time Protocol (PTP). A class driver offers a registration method to particular hardware clock drivers. Each clock is exposed to user space as a character device with ioctls that allow tuning of the PTP clock. Signed-off-by: Richard Cochran richard.coch...@omicron.at Hi Richard, Some more comments on this patch... --- Documentation/ptp/ptp.txt | 95 +++ Documentation/ptp/testptp.c | 269 Documentation/ptp/testptp.mk | 33 +++ drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/ptp/Kconfig | 26 ++ drivers/ptp/Makefile | 5 + drivers/ptp/ptp_clock.c | 514 ++ include/linux/Kbuild | 1 + include/linux/ptp_clock.h | 79 ++ include/linux/ptp_clock_kernel.h | 137 ++ 11 files changed, 1162 insertions(+), 0 deletions(-) create mode 100644 Documentation/ptp/ptp.txt create mode 100644 Documentation/ptp/testptp.c create mode 100644 Documentation/ptp/testptp.mk create mode 100644 drivers/ptp/Kconfig create mode 100644 drivers/ptp/Makefile create mode 100644 drivers/ptp/ptp_clock.c create mode 100644 include/linux/ptp_clock.h create mode 100644 include/linux/ptp_clock_kernel.h diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile new file mode 100644 index 000..b86695c --- /dev/null +++ b/drivers/ptp/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for PTP 1588 clock support. +# + +obj-$(CONFIG_PTP_1588_CLOCK) += ptp_clock.o diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c new file mode 100644 index 000..4753bf3 --- /dev/null +++ b/drivers/ptp/ptp_clock.c @@ -0,0 +1,514 @@ +/* + * PTP 1588 clock support + * + * Partially adapted from the Linux PPS driver. + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include linux/bitops.h +#include linux/cdev.h +#include linux/device.h +#include linux/init.h +#include linux/kernel.h +#include linux/list.h +#include linux/module.h +#include linux/poll.h +#include linux/sched.h +#include linux/slab.h +#include linux/uaccess.h + +#include linux/ptp_clock_kernel.h +#include linux/ptp_clock.h + +#define PTP_MAX_ALARMS 4 +#define PTP_MAX_CLOCKS BITS_PER_LONG +#define PTP_MAX_TIMESTAMPS 128 + +struct alarm { + struct pid *pid; + int sig; +}; + +struct timestamp_event_queue { + struct ptp_extts_event buf[PTP_MAX_TIMESTAMPS]; + int head; + int tail; + int overflow; +}; + +struct ptp_clock { + struct list_head list; + struct cdev cdev; + struct device *dev; + struct ptp_clock_info *info; + dev_t devid; + int index; /* index into clocks.map, also the minor number */ + + struct alarm alarm[PTP_MAX_ALARMS]; + struct mutex alarm_mux; /* one process at a time setting an alarm */ + + struct timestamp_event_queue tsevq; /* simple fifo for time stamps */ + struct mutex tsevq_mux; /* one process at a time reading the fifo */ + wait_queue_head_t tsev_wq; +}; + +/* private globals */ + +static const struct file_operations ptp_fops; +static dev_t ptp_devt; +static struct class *ptp_class; + +static struct { + struct list_head list; + DECLARE_BITMAP(map, PTP_MAX_CLOCKS); +} clocks; +static DEFINE_SPINLOCK(clocks_lock); /* protects 'clocks' */ Doesn't appear that clocks is manipulated at atomic context. Mutex instead? + +/* time stamp event queue operations */ + +static inline int queue_cnt(struct timestamp_event_queue *q) +{ + int cnt = q-tail - q-head; + return cnt 0 ? PTP_MAX_TIMESTAMPS + cnt : cnt; +} + +static inline int queue_free(struct timestamp_event_queue *q) +{ + return PTP_MAX_TIMESTAMPS - queue_cnt(q) - 1; +} + +static void enqueue_external_timestamp(struct timestamp_event_queue *queue, + struct ptp_clock_event *src) +{ + struct ptp_extts_event
Re: [PATCH 1/2] ehea: fix delayed packet processing
Jan-Bernd Themann ossth...@de.ibm.com wrote: In the eHEA poll function an rmb() is required. Without that some packets on the receive queue are not seen and thus delayed until the next interrupt is handled for the same receive queue. Signed-off-by: Jan-Bernd Themann them...@de.ibm.com To add a bit of background, this could manifest during a netperf TCP_RR or UDP_RR on an otherwise idle network. TCP would occasionally retransmit, but then both the original segment and the retransmission would simultaneously appear at the receiver. For UDP_RR, message sizes in excess of the mtu would occasionally lose an IP fragment, and eventually IP reassembly would time out. -J Signed-off-by: Jay Vosburgh fu...@us.ibm.com --- Patch created against 2.6.35-rc3 drivers/net/ehea/ehea_main.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index f547894..fd890fa 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -867,6 +867,7 @@ static int ehea_poll(struct napi_struct *napi, int budget) ehea_reset_cq_ep(pr-send_cq); ehea_reset_cq_n1(pr-recv_cq); ehea_reset_cq_n1(pr-send_cq); + rmb(); cqe = ehea_poll_rq1(pr-qp, wqe_index); cqe_skb = ehea_poll_cq(pr-send_cq); -- 1.7.0 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/2 v4] powerpc/5200: add mpc5200_psc_ac97_gpio_reset
Work around a silicon bug in the ac97 reset functionality of the mpc5200(b). The implementation of the ac97 cold reset is flawed. If the sync and output lines are high when reset is asserted the attached ac97 device may go into test mode. Avoid this by reconfiguring the psc to gpio mode and generating the reset manually. From MPC5200B User's Manual: Some AC97 devices goes to a test mode, if the Sync line is high during the Res line is low (reset phase). To avoid this behavior the Sync line must be also forced to zero during the reset phase. To do that, the pin muxing should switch to GPIO mode and the GPIO control register should be used to control the output lines. Signed-off-by: Eric Millbrandt emillbra...@dekaresearch.com --- changes since v1 - Amended with comments from Mark Brown - Fall back to the original reset implementation if no gpio pins are defined in the device tree changes since v2 - Refactored to move the port_config manipulation to platform code. - Remove the gpio pins from the device-tree changes since v3 - Remove redundant checks around call to mpc5200_psc_ac97_gpio_reset() changes since v4 - cleanup inverted logic arch/powerpc/include/asm/mpc52xx.h |1 + arch/powerpc/include/asm/mpc52xx_psc.h |1 + arch/powerpc/platforms/52xx/mpc52xx_common.c | 111 ++ 3 files changed, 113 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/include/asm/mpc52xx.h b/arch/powerpc/include/asm/mpc52xx.h index b664ce7..1f41382 100644 --- a/arch/powerpc/include/asm/mpc52xx.h +++ b/arch/powerpc/include/asm/mpc52xx.h @@ -271,6 +271,7 @@ struct mpc52xx_intr { /* mpc52xx_common.c */ extern void mpc5200_setup_xlb_arbiter(void); extern void mpc52xx_declare_of_platform_devices(void); +extern int mpc5200_psc_ac97_gpio_reset(int psc_number); extern void mpc52xx_map_common_devices(void); extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv); extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node); diff --git a/arch/powerpc/include/asm/mpc52xx_psc.h b/arch/powerpc/include/asm/mpc52xx_psc.h index ecc4fc6..2966df6 100644 --- a/arch/powerpc/include/asm/mpc52xx_psc.h +++ b/arch/powerpc/include/asm/mpc52xx_psc.h @@ -131,6 +131,7 @@ #define MPC52xx_PSC_SICR_SIM_FIR (0x6 24) #define MPC52xx_PSC_SICR_SIM_CODEC_24 (0x7 24) #define MPC52xx_PSC_SICR_SIM_CODEC_32 (0xf 24) +#define MPC52xx_PSC_SICR_ACRB (0x8 24) #define MPC52xx_PSC_SICR_AWR (1 30) #define MPC52xx_PSC_SICR_GENCLK(1 23) #define MPC52xx_PSC_SICR_I2S (1 22) diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index a46bad0..1887872 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -12,9 +12,11 @@ #undef DEBUG +#include linux/gpio.h #include linux/kernel.h #include linux/spinlock.h #include linux/of_platform.h +#include linux/of_gpio.h #include asm/io.h #include asm/prom.h #include asm/mpc52xx.h @@ -82,6 +84,14 @@ mpc5200_setup_xlb_arbiter(void) iounmap(xlb); } +/* + * This variable is mapped in mpc52xx_map_common_devices and + * used in mpc5200_psc_ac97_gpio_reset(). + */ +static DEFINE_SPINLOCK(gpio_lock); +struct mpc52xx_gpio __iomem *simple_gpio; +struct mpc52xx_gpio_wkup __iomem *wkup_gpio; + /** * mpc52xx_declare_of_platform_devices: register internal devices and children * of the localplus bus to the of_platform @@ -109,6 +119,19 @@ static struct of_device_id mpc52xx_cdm_ids[] __initdata = { { .compatible = mpc5200-cdm, }, /* old */ {} }; +static const struct of_device_id mpc52xx_gpio_simple[] = { + { + .compatible = fsl,mpc5200-gpio, + }, + {} +}; +static const struct of_device_id mpc52xx_gpio_wkup[] = { + { + .compatible = fsl,mpc5200-gpio-wkup, + }, + {} +}; + /** * mpc52xx_map_common_devices: iomap devices required by common code @@ -135,6 +158,16 @@ mpc52xx_map_common_devices(void) np = of_find_matching_node(NULL, mpc52xx_cdm_ids); mpc52xx_cdm = of_iomap(np, 0); of_node_put(np); + + /* simple_gpio registers */ + np = of_find_matching_node(NULL, mpc52xx_gpio_simple); + simple_gpio = of_iomap(np, 0); + of_node_put(np); + + /* wkup_gpio registers */ + np = of_find_matching_node(NULL, mpc52xx_gpio_wkup); + wkup_gpio = of_iomap(np, 0); + of_node_put(np); } /** @@ -233,3 +266,81 @@ mpc52xx_restart(char *cmd) while (1); } + +#define PSC1_RESET 0x1 +#define PSC1_SYNC 0x4 +#define PSC1_SDATA_OUT 0x1 +#define PSC2_RESET 0x2 +#define PSC2_SYNC (0x44) +#define PSC2_SDATA_OUT (0x14) +#define MPC52xx_GPIO_PSC1_MASK 0x7 +#define MPC52xx_GPIO_PSC2_MASK (0x74) + +/** + * mpc5200_psc_ac97_gpio_reset: Use gpio pins
Porting a driver to powerpc using FDT
I am trying to port a DSA (Distributed Switch Architecture) driver for the Micrel KS8995M managed switch connected to a MPC5200. There is an SPI interface and MII interface managed by the DSA driver. I can't understand how probe gets called when the flatted device tree (FDT) system is used, and how to bind such a driver using the FDT (if you have to at all). The DSA driver is initialised via: // net/dsa/dsa.c static struct platform_driver dsa_driver = { .probe = dsa_probe, .remove = dsa_remove, .shutdown = dsa_shutdown, .driver = { .name = dsa, .owner = THIS_MODULE, }, }; static int __init dsa_init_module(void) { return platform_driver_register(dsa_driver); } dsa_init_module is being called; but how do I get the system to call .probe? Chris ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2] lite5200: fix ethernet phy address
Dmitry Eremin-Solenikov wrote: According to my schematics, on Lite5200 board ethernet phy uses address 0 (all ADDR lines are pulled down). With this change I can talk to onboard phy (LXT971) and correctly use autonegotiation. What about this patch? -- With best wishes Dmitry ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Porting a driver to powerpc using FDT
I am trying to port a DSA (Distributed Switch Architecture) driver for the Micrel KS8995M managed switch connected to a MPC5200. There is an SPI interface and MII interface managed by the DSA driver. I can't understand how probe gets called when the flatted device tree (FDT) system is used, and how to bind such a driver using the FDT (if you have to at all). The DSA driver is initialised via: // net/dsa/dsa.c static struct platform_driver dsa_driver = { .probe = dsa_probe, .remove = dsa_remove, .shutdown = dsa_shutdown, .driver = { .name = dsa, .owner = THIS_MODULE, }, }; static int __init dsa_init_module(void) { return platform_driver_register(dsa_driver); } dsa_init_module is being called; but how do I get the system to call .probe? Chris ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 5/5] of/address: restrict 'no-ranges' kludge to powerpc
On Tue, 2010-06-15 at 18:23 +0200, Segher Boessenkool wrote: Certain Apple machines don't use the ranges property correctly, but the workaround should not be applied on other architectures. This patch disables the workaround for non-powerpc architectures. I'm half tempted to add it to the quirk list (which should really be made generic) so I can disable it on more 'modern' powerpc as well. Oh please oh please oh please yes do. OTOH, it would be even better to just fix up the device tree in the early platform code. Quirks are for broken hardware; software, we can fix. That would work if I could bloody remember which machines need what on what nodes ... some of those are ancient and I don't have access to all of them. Cheers, Ben. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH RFC] ppc: fix default_machine_crash_shutdown #ifdef botch
crash_kexec_wait_realmode() is defined only if CONFIG_PPC_STD_MMU_64 and CONFIG_SMP, but is called if CONFIG_PPC_STD_MMU_64 even if !CONFIG_SMP. Fix the conditional compilation around the invocation. Untested, probably does not compile. Signed-off-by: Paul E. McKenney paul...@linux.vnet.ibm.com --- diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index b46f2e0..29df48f 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -447,7 +447,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs) crash_kexec_prepare_cpus(crashing_cpu); cpu_set(crashing_cpu, cpus_in_crash); crash_kexec_stop_spus(); -#ifdef CONFIG_PPC_STD_MMU_64 +#if defined(CONFIG_PPC_STD_MMU_64) defined(CONFIG_SMP) crash_kexec_wait_realmode(crashing_cpu); #endif if (ppc_md.kexec_cpu_down) ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] Restore kexec uImage-ppc to working state
CCed linuxppc-dev to fish for an ack. On Mon, Jun 14, 2010 at 02:38:42PM -0500, Matthew McClintock wrote: Booting with uImage-ppc was broken by previous work, this patch should restore it to working order Signed-off-by: Matthew McClintock m...@freescale.com --- kexec/arch/ppc/kexec-ppc.c | 68 ++- kexec/arch/ppc/kexec-uImage-ppc.c |5 +-- purgatory/arch/ppc/purgatory-ppc.c |5 +++ 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c index 55cadd6..c073f56 100644 --- a/kexec/arch/ppc/kexec-ppc.c +++ b/kexec/arch/ppc/kexec-ppc.c @@ -261,11 +261,28 @@ static int get_base_ranges(void) break; } } - base_memory_range[local_memory_ranges].start = - ((uint32_t *)buf)[0]; - base_memory_range[local_memory_ranges].end = - base_memory_range[local_memory_ranges].start + - ((uint32_t *)buf)[1]; + + if (n == 8) + { + base_memory_range[local_memory_ranges].start = + ((uint32_t *)buf)[0]; + base_memory_range[local_memory_ranges].end = + base_memory_range[local_memory_ranges].start + + ((uint32_t *)buf)[1]; + } + else if (n == 16) + { + base_memory_range[local_memory_ranges].start = +((uint64_t *)buf)[0]; +base_memory_range[local_memory_ranges].end = + base_memory_range[local_memory_ranges].start + +((uint64_t *)buf)[1]; + } + else + { + fprintf(stderr, Mem node has invalid size: %d\n, n); + return -1; + } base_memory_range[local_memory_ranges].type = RANGE_RAM; local_memory_ranges++; dbgprintf(%016llx-%016llx : %x\n, @@ -327,27 +344,28 @@ static int get_devtree_details(unsigned long kexec_flags) } if (strncmp(dentry-d_name, chosen, 6) == 0) { - strcat(fname, /linux,kernel-end); - file = fopen(fname, r); - if (!file) { - perror(fname); - goto error_opencdir; - } - if (fread(tmp_long, sizeof(unsigned long), 1, file) - != 1) { - perror(fname); - goto error_openfile; - } - kernel_end = tmp_long; - fclose(file); - - /* Add kernel memory to exclude_range */ - exclude_range[i].start = 0x0UL; - exclude_range[i].end = kernel_end; - i++; - if (i = max_memory_ranges) - realloc_memory_ranges(); + /* only reserve kernel region if we are doing a crash kernel */ if (kexec_flags KEXEC_ON_CRASH) { + strcat(fname, /linux,kernel-end); + file = fopen(fname, r); + if (!file) { + perror(fname); + goto error_opencdir; + } + if (fread(tmp_long, sizeof(unsigned long), 1, file) + != 1) { + perror(fname); + goto error_openfile; + } + kernel_end = tmp_long; + fclose(file); + + /* Add kernel memory to exclude_range */ + exclude_range[i].start = 0x0UL; + exclude_range[i].end = kernel_end; + i++; + if (i = max_memory_ranges) + realloc_memory_ranges(); memset(fname, 0, sizeof(fname)); strcpy(fname, device_tree); strcat(fname, dentry-d_name); diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c
Re: [PATCH 04/12] phylib: add a way to make PHY time stamps possible.
On Tue, Jun 15, 2010 at 10:33:51AM -0600, Grant Likely wrote: +config NETWORK_PHY_TIMESTAMPING Some overhead? At a brief glance of the series it looks like it could add a lot of overhead, but I'm not fully clear on what the full process is. Can you describe how the hardware timestamping works? I could use an overview of what the kernel has to do. First of all, I want to emphasize that this network stack option is purely voluntary. Only those people who know that they have a PTP capable PHY and really want the timestamps will (or should) enable this option. When it is not enabled, it has no effect at all. Hardware timestamping is described in Documentation/networking/timestamping.txt Documentation/networking/timestamping/timestamping.c The PTP subsystem is described in Documentation/ptp/ptp.txt There really is more to say about the issue than appears in those documents, but they are a good starting place for discussion. BTW I am submitting a conference paper on the design on the PTP subsystem. If you would like to have it, just ask me off-list. Richard ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev