Home Home > GIT Browse
summaryrefslogtreecommitdiff
authorOlaf Hering <olh@suse.de>2008-10-31 14:24:07 (GMT)
committer Olaf Hering <olh@suse.de>2008-10-31 14:24:07 (GMT)
commit6ce42bd4b996dbb9c832483363bf0541bc09a685 (patch) (side-by-side diff)
tree1da62ac39a34c0dce23a0e539c7cc47630765f19
parentffd0073565c49bad54bd98c86e6ff6b5bd82d421 (diff)
+- add patches.arch/ppc-clock_gettime-nanoseconds.patchrpm-2.6.16.60-0.33
+ update also nanoseconds (bnc#439908 - LTC49499)
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--kernel-source.changes6
-rw-r--r--patches.arch/ppc-clock_gettime-nanoseconds.patch491
-rw-r--r--series.conf1
3 files changed, 498 insertions, 0 deletions
diff --git a/kernel-source.changes b/kernel-source.changes
index 673922e..bba3a41 100644
--- a/kernel-source.changes
+++ b/kernel-source.changes
@@ -1,7 +1,13 @@
-------------------------------------------------------------------
+Fri Oct 31 15:00:29 CET 2008 - olh@suse.de
+
+- add patches.arch/ppc-clock_gettime-nanoseconds.patch
+ update also nanoseconds (bnc#439908 - LTC49499)
+
+-------------------------------------------------------------------
Fri Oct 31 03:08:08 CET 2008 - jjolly@suse.de
- patches.arch/s390-26-01-qeth-recover-iff-up.patch: qeth: avoid
problems after failing recovery (bnc#434323,LTC#48636)
- patches.arch/s390-26-02-qeth-tso.patch: qeth: EDDP for large TSO
skb fragment list (bnc#434323,LTC#49146)
diff --git a/patches.arch/ppc-clock_gettime-nanoseconds.patch b/patches.arch/ppc-clock_gettime-nanoseconds.patch
new file mode 100644
index 0000000..4eb8e00
--- a/dev/null
+++ b/patches.arch/ppc-clock_gettime-nanoseconds.patch
@@ -0,0 +1,491 @@
+Subject: update also nanoseconds in clock_gettime
+From: Mike Wolf <mjw@linux.vnet.ibm.com>
+References: 439908 - LTC49499
+
+
+Signed-off-by: Olaf Hering <olh@suse.de>
+---
+ arch/powerpc/kernel/asm-offsets.c | 1
+ arch/powerpc/kernel/time.c | 1
+ arch/powerpc/kernel/vdso32/gettimeofday.S | 196 ++++++++++++++++++------------
+ arch/powerpc/kernel/vdso64/gettimeofday.S | 140 +++++++++++----------
+ include/asm-powerpc/vdso_datapage.h | 3
+ 5 files changed, 202 insertions(+), 139 deletions(-)
+
+--- a/arch/powerpc/kernel/asm-offsets.c
++++ b/arch/powerpc/kernel/asm-offsets.c
+@@ -279,6 +279,7 @@ int main(void)
+ DEFINE(CFG_SYSCALL_MAP32, offsetof(struct vdso_data, syscall_map_32));
+ DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec));
+ DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
++ DEFINE(STAMP_XTIME, offsetof(struct vdso_data, stamp_xtime));
+ #ifdef CONFIG_PPC64
+ DEFINE(CFG_SYSCALL_MAP64, offsetof(struct vdso_data, syscall_map_64));
+ DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec));
+--- a/arch/powerpc/kernel/time.c
++++ b/arch/powerpc/kernel/time.c
+@@ -507,6 +507,7 @@ static inline void update_gtod(u64 new_t
+ vdso_data->tb_to_xs = new_tb_to_xs;
+ vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec;
+ vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec;
++ vdso_data->stamp_xtime = xtime;
+ smp_wmb();
+ ++(vdso_data->tb_update_count);
+ }
+--- a/arch/powerpc/kernel/vdso32/gettimeofday.S
++++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
+@@ -17,6 +17,13 @@
+ #include <asm/asm-offsets.h>
+ #include <asm/unistd.h>
+
++/* Offset for the low 32-bit part of a field of long type */
++#ifdef CONFIG_PPC64
++#define LOPART 4
++#else
++#define LOPART 0
++#endif
++
+ .text
+ /*
+ * Exact prototype of gettimeofday
+@@ -89,101 +96,53 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
+
+ mflr r12 /* r12 saves lr */
+ .cfi_register lr,r12
+- mr r10,r3 /* r10 saves id */
+ mr r11,r4 /* r11 saves tp */
+ bl __get_datapage@local /* get data page */
+ mr r9,r3 /* datapage ptr in r9 */
+- beq cr1,50f /* if monotonic -> jump there */
+-
+- /*
+- * CLOCK_REALTIME
+- */
+-
+- bl __do_get_xsec@local /* get xsec from tb & kernel */
+- bne- 98f /* out of line -> do syscall */
+-
+- /* seconds are xsec >> 20 */
+- rlwinm r5,r4,12,20,31
+- rlwimi r5,r3,12,0,19
+- stw r5,TSPC32_TV_SEC(r11)
+
+- /* get remaining xsec and convert to nsec. we scale
+- * up remaining xsec by 12 bits and get the top 32 bits
+- * of the multiplication, then we multiply by 1000
+- */
+- rlwinm r5,r4,12,0,19
+- lis r6,1000000@h
+- ori r6,r6,1000000@l
+- mulhwu r5,r5,r6
+- mulli r5,r5,1000
+- stw r5,TSPC32_TV_NSEC(r11)
+- mtlr r12
+- crclr cr0*4+so
+- li r3,0
+- blr
++50: bl __do_get_tspec@local /* get sec/nsec from tb & kernel */
++ bne cr1,80f /* not monotonic -> all done */
+
+ /*
+ * CLOCK_MONOTONIC
+ */
+
+-50: bl __do_get_xsec@local /* get xsec from tb & kernel */
+- bne- 98f /* out of line -> do syscall */
+-
+- /* seconds are xsec >> 20 */
+- rlwinm r6,r4,12,20,31
+- rlwimi r6,r3,12,0,19
+-
+- /* get remaining xsec and convert to nsec. we scale
+- * up remaining xsec by 12 bits and get the top 32 bits
+- * of the multiplication, then we multiply by 1000
+- */
+- rlwinm r7,r4,12,0,19
+- lis r5,1000000@h
+- ori r5,r5,1000000@l
+- mulhwu r7,r7,r5
+- mulli r7,r7,1000
+-
+ /* now we must fixup using wall to monotonic. We need to snapshot
+ * that value and do the counter trick again. Fortunately, we still
+ * have the counter value in r8 that was returned by __do_get_xsec.
+- * At this point, r6,r7 contain our sec/nsec values, r3,r4 and r5
+- * can be used
++ * At this point, r3,r4 contain our sec/nsec values, r5 and r6
++ * can be used, r7 contains NSEC_PER_SEC.
+ */
+
+- lwz r3,WTOM_CLOCK_SEC(r9)
+- lwz r4,WTOM_CLOCK_NSEC(r9)
++ lwz r5,WTOM_CLOCK_SEC(r9)
++ lwz r6,WTOM_CLOCK_NSEC(r9)
+
+- /* We now have our result in r3,r4. We create a fake dependency
+- * on that result and re-check the counter
++ /* We now have our offset in r5,r6. We create a fake dependency
++ * on that value and re-check the counter
+ */
+- or r5,r4,r3
+- xor r0,r5,r5
++ or r0,r6,r5
++ xor r0,r0,r0
+ add r9,r9,r0
+-#ifdef CONFIG_PPC64
+- lwz r0,(CFG_TB_UPDATE_COUNT+4)(r9)
+-#else
+- lwz r0,(CFG_TB_UPDATE_COUNT)(r9)
+-#endif
++ lwz r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
+ cmpl cr0,r8,r0 /* check if updated */
+ bne- 50b
+
+- /* Calculate and store result. Note that this mimmics the C code,
++ /* Calculate and store result. Note that this mimics the C code,
+ * which may cause funny results if nsec goes negative... is that
+ * possible at all ?
+ */
+- add r3,r3,r6
+- add r4,r4,r7
+- lis r5,NSEC_PER_SEC@h
+- ori r5,r5,NSEC_PER_SEC@l
+- cmpl cr0,r4,r5
+- cmpli cr1,r4,0
++ add r3,r3,r5
++ add r4,r4,r6
++ cmpw cr0,r4,r7
++ cmpwi cr1,r4,0
+ blt 1f
+- subf r4,r5,r4
++ subf r4,r7,r4
+ addi r3,r3,1
+-1: bge cr1,1f
++1: bge cr1,80f
+ addi r3,r3,-1
+- add r4,r4,r5
+-1: stw r3,TSPC32_TV_SEC(r11)
++ add r4,r4,r7
++
++80: stw r3,TSPC32_TV_SEC(r11)
+ stw r4,TSPC32_TV_NSEC(r11)
+
+ mtlr r12
+@@ -194,10 +153,6 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
+ /*
+ * syscall fallback
+ */
+-98:
+- mtlr r12
+- mr r3,r10
+- mr r4,r11
+ 99:
+ li r0,__NR_clock_gettime
+ sc
+@@ -321,3 +276,98 @@ __do_get_xsec:
+ */
+ 3: blr
+ .cfi_endproc
++
++/*
++ * This is the core of clock_gettime(), it returns the current
++ * time in seconds and nanoseconds in r3 and r4.
++ * It expects the datapage ptr in r9 and doesn't clobber it.
++ * It clobbers r0, r5, r6, r10 and returns NSEC_PER_SEC in r7.
++ * On return, r8 contains the counter value that can be reused.
++ * This clobbers cr0 but not any other cr field.
++ */
++__do_get_tspec:
++ .cfi_startproc
++ /* Check for update count & load values. We use the low
++ * order 32 bits of the update count
++ */
++1: lwz r8,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
++ andi. r0,r8,1 /* pending update ? loop */
++ bne- 1b
++ xor r0,r8,r8 /* create dependency */
++ add r9,r9,r0
++
++ /* Load orig stamp (offset to TB) */
++ lwz r5,CFG_TB_ORIG_STAMP(r9)
++ lwz r6,(CFG_TB_ORIG_STAMP+4)(r9)
++
++ /* Get a stable TB value */
++2: mftbu r3
++ mftbl r4
++ mftbu r0
++ cmpl cr0,r3,r0
++ bne- 2b
++
++ /* Subtract tb orig stamp and shift left 12 bits.
++ */
++ subfc r7,r6,r4
++ subfe r0,r5,r3
++ slwi r0,r0,12
++ rlwimi. r0,r7,12,20,31
++ slwi r7,r7,12
++
++ /* Load scale factor & do multiplication */
++ lwz r5,CFG_TB_TO_XS(r9) /* load values */
++ lwz r6,(CFG_TB_TO_XS+4)(r9)
++ mulhwu r3,r7,r6
++ mullw r10,r7,r5
++ mulhwu r4,r7,r5
++ addc r10,r3,r10
++ li r3,0
++
++ beq+ 4f /* skip high part computation if 0 */
++ mulhwu r3,r0,r5
++ mullw r7,r0,r5
++ mulhwu r5,r0,r6
++ mullw r6,r0,r6
++ adde r4,r4,r7
++ addze r3,r3
++ addc r4,r4,r5
++ addze r3,r3
++ addc r10,r10,r6
++
++4: addze r4,r4 /* add in carry */
++ lis r7,NSEC_PER_SEC@h
++ ori r7,r7,NSEC_PER_SEC@l
++ mulhwu r4,r4,r7 /* convert to nanoseconds */
++
++ /* At this point, we have seconds & nanoseconds since the xtime
++ * stamp in r3+CA and r4. Load & add the xtime stamp.
++ */
++#ifdef CONFIG_PPC64
++ lwz r5,STAMP_XTIME+TSPC64_TV_SEC+LOPART(r9)
++ lwz r6,STAMP_XTIME+TSPC64_TV_NSEC+LOPART(r9)
++#else
++ lwz r5,STAMP_XTIME+TSPC32_TV_SEC(r9)
++ lwz r6,STAMP_XTIME+TSPC32_TV_NSEC(r9)
++#endif
++ add r4,r4,r6
++ adde r3,r3,r5
++
++ /* We now have our result in r3,r4. We create a fake dependency
++ * on that result and re-check the counter
++ */
++ or r6,r4,r3
++ xor r0,r6,r6
++ add r9,r9,r0
++ lwz r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
++ cmpl cr0,r8,r0 /* check if updated */
++ bne- 1b
++
++ /* check for nanosecond overflow and adjust if necessary */
++ cmpw r4,r7
++ bltlr /* all done if no overflow */
++ subf r4,r7,r4 /* adjust if overflow */
++ addi r3,r3,1
++
++ blr
++ .cfi_endproc
+--- a/arch/powerpc/kernel/vdso64/gettimeofday.S
++++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
+@@ -75,90 +75,49 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
+
+ mflr r12 /* r12 saves lr */
+ .cfi_register lr,r12
+- mr r10,r3 /* r10 saves id */
+ mr r11,r4 /* r11 saves tp */
+ bl V_LOCAL_FUNC(__get_datapage) /* get data page */
+- beq cr1,50f /* if monotonic -> jump there */
+-
+- /*
+- * CLOCK_REALTIME
+- */
+-
+- bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
+-
+- lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
+- ori r7,r7,16960
+- rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
+- rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
+- std r5,TSPC64_TV_SEC(r11) /* store sec in tv */
+- subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
+- mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
+- * XSEC_PER_SEC
+- */
+- rldicl r0,r0,44,20
+- mulli r0,r0,1000 /* nsec = usec * 1000 */
+- std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */
+-
+- mtlr r12
+- crclr cr0*4+so
+- li r3,0
+- blr
++50: bl V_LOCAL_FUNC(__do_get_tspec) /* get time from tb & kernel */
++ bne cr1,80f /* if not monotonic, all done */
+
+ /*
+ * CLOCK_MONOTONIC
+ */
+
+-50: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
+-
+- lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
+- ori r7,r7,16960
+- rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
+- rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
+- subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
+- mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
+- * XSEC_PER_SEC
+- */
+- rldicl r6,r0,44,20
+- mulli r6,r6,1000 /* nsec = usec * 1000 */
+-
+ /* now we must fixup using wall to monotonic. We need to snapshot
+ * that value and do the counter trick again. Fortunately, we still
+- * have the counter value in r8 that was returned by __do_get_xsec.
+- * At this point, r5,r6 contain our sec/nsec values.
+- * can be used
++ * have the counter value in r8 that was returned by __do_get_tspec.
++ * At this point, r4,r5 contain our sec/nsec values.
+ */
+
+- lwa r4,WTOM_CLOCK_SEC(r3)
+- lwa r7,WTOM_CLOCK_NSEC(r3)
++ lwa r6,WTOM_CLOCK_SEC(r3)
++ lwa r9,WTOM_CLOCK_NSEC(r3)
+
+- /* We now have our result in r4,r7. We create a fake dependency
++ /* We now have our result in r6,r9. We create a fake dependency
+ * on that result and re-check the counter
+ */
+- or r9,r4,r7
+- xor r0,r9,r9
++ or r0,r6,r9
++ xor r0,r0,r0
+ add r3,r3,r0
+ ld r0,CFG_TB_UPDATE_COUNT(r3)
+ cmpld cr0,r0,r8 /* check if updated */
+ bne- 50b
+
+- /* Calculate and store result. Note that this mimmics the C code,
+- * which may cause funny results if nsec goes negative... is that
+- * possible at all ?
+- */
+- add r4,r4,r5
+- add r7,r7,r6
+- lis r9,NSEC_PER_SEC@h
+- ori r9,r9,NSEC_PER_SEC@l
+- cmpl cr0,r7,r9
+- cmpli cr1,r7,0
++ /* Add wall->monotonic offset and check for overflow or underflow.
++ */
++ add r4,r4,r6
++ add r5,r5,r9
++ cmpd cr0,r5,r7
++ cmpdi cr1,r5,0
+ blt 1f
+- subf r7,r9,r7
++ subf r5,r7,r5
+ addi r4,r4,1
+-1: bge cr1,1f
++1: bge cr1,80f
+ addi r4,r4,-1
+- add r7,r7,r9
+-1: std r4,TSPC64_TV_SEC(r11)
+- std r7,TSPC64_TV_NSEC(r11)
++ add r5,r5,r7
++
++80: std r4,TSPC64_TV_SEC(r11)
++ std r5,TSPC64_TV_NSEC(r11)
+
+ mtlr r12
+ crclr cr0*4+so
+@@ -168,10 +127,6 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
+ /*
+ * syscall fallback
+ */
+-98:
+- mtlr r12
+- mr r3,r10
+- mr r4,r11
+ 99:
+ li r0,__NR_clock_gettime
+ sc
+@@ -251,3 +206,56 @@ V_FUNCTION_BEGIN(__do_get_xsec)
+ blr
+ .cfi_endproc
+ V_FUNCTION_END(__do_get_xsec)
++
++/*
++ * This is the core of clock_gettime(), it returns the current
++ * time in seconds and nanoseconds in r4 and r5.
++ * It expects the datapage ptr in r3 and doesn't clobber it.
++ * It clobbers r0 and r6 and returns NSEC_PER_SEC in r7.
++ * On return, r8 contains the counter value that can be reused.
++ * This clobbers cr0 but not any other cr field.
++ */
++V_FUNCTION_BEGIN(__do_get_tspec)
++ .cfi_startproc
++ /* check for update count & load values */
++1: ld r8,CFG_TB_UPDATE_COUNT(r3)
++ andi. r0,r8,1 /* pending update ? loop */
++ bne- 1b
++ xor r0,r8,r8 /* create dependency */
++ add r3,r3,r0
++
++ mftb r7
++ ld r9,CFG_TB_ORIG_STAMP(r3)
++ subf r7,r9,r7
++
++ /* Scale result */
++ ld r5,CFG_TB_TO_XS(r3)
++ sldi r7,r7,12 /* compute time since stamp_xtime */
++ mulhdu r6,r7,r5 /* in units of 2^-32 seconds */
++
++ /* Add stamp since epoch */
++ ld r4,STAMP_XTIME+TSPC64_TV_SEC(r3)
++ ld r5,STAMP_XTIME+TSPC64_TV_NSEC(r3)
++ or r0,r4,r5
++ or r0,r0,r6
++ xor r0,r0,r0
++ add r3,r3,r0
++ ld r0,CFG_TB_UPDATE_COUNT(r3)
++ cmpld r0,r8 /* check if updated */
++ bne- 1b /* reload if so */
++
++ /* convert to seconds & nanoseconds and add to stamp */
++ lis r7,NSEC_PER_SEC@h
++ ori r7,r7,NSEC_PER_SEC@l
++ mulhwu r0,r6,r7 /* compute nanoseconds and */
++ srdi r6,r6,32 /* seconds since stamp_xtime */
++ clrldi r0,r0,32
++ add r5,r5,r0 /* add nanoseconds together */
++ cmpd r5,r7 /* overflow? */
++ add r4,r4,r6
++ bltlr /* all done if no overflow */
++ subf r5,r7,r5 /* if overflow, adjust */
++ addi r4,r4,1
++ blr
++ .cfi_endproc
++V_FUNCTION_END(__do_get_ysec)
+--- a/include/asm-powerpc/vdso_datapage.h
++++ b/include/asm-powerpc/vdso_datapage.h
+@@ -39,6 +39,7 @@
+ #ifndef __ASSEMBLY__
+
+ #include <linux/unistd.h>
++#include <linux/time.h>
+
+ #define SYSCALL_MAP_SIZE ((__NR_syscalls + 31) / 32)
+
+@@ -76,6 +77,7 @@ struct vdso_data {
+ */
+ __s32 wtom_clock_sec; /* Wall to monotonic clock */
+ __s32 wtom_clock_nsec;
++ struct timespec stamp_xtime; /* xtime value for tb_orig_stamp */
+ __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls */
+ __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
+ };
+@@ -95,6 +97,7 @@ struct vdso_data {
+ __u32 tz_dsttime; /* Type of dst correction 0x5C */
+ __s32 wtom_clock_sec; /* Wall to monotonic clock */
+ __s32 wtom_clock_nsec;
++ struct timespec stamp_xtime; /* xtime value for tb_orig_stamp */
+ __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
+ };
+
diff --git a/series.conf b/series.conf
index 22f3c27..cbc3cde 100644
--- a/series.conf
+++ b/series.conf
@@ -553,12 +553,13 @@
patches.arch/ppc-dedicated_idle_sleep.patch
patches.arch/ppc-slb_size_from_devicetree.patch
patches.arch/ppc-dlpar-cpu-irq.patch
patches.arch/ppc-clear-ri-bit.patch
patches.arch/ppc-eeh-use-device-endpoint.patch
patches.arch/ppc-dabr-multiple-threads.patch
+ patches.arch/ppc-clock_gettime-nanoseconds.patch
patches.suse/delayacct-scaled-cpu.patch
########################################################
# s390, IBM patches first
########################################################