Commit 8c3076d4 authored by Anton Blanchard's avatar Anton Blanchard

ppc64: iSeries updates from iSeries team

ppc64: time updates from Mike Corrigan
ppc64: add flush_hash_range for pSeries LPAR
ppc64: align syscall tables to 8 bytes
parent 0eef6190
...@@ -53,6 +53,8 @@ struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * lpQueue ) ...@@ -53,6 +53,8 @@ struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * lpQueue )
struct HvLpEvent * nextLpEvent = struct HvLpEvent * nextLpEvent =
(struct HvLpEvent *)lpQueue->xSlicCurEventPtr; (struct HvLpEvent *)lpQueue->xSlicCurEventPtr;
if ( nextLpEvent->xFlags.xValid ) { if ( nextLpEvent->xFlags.xValid ) {
/* rmb() needed only for weakly consistent machines (regatta) */
rmb();
/* Set pointer to next potential event */ /* Set pointer to next potential event */
lpQueue->xSlicCurEventPtr += ((nextLpEvent->xSizeMinus1 + lpQueue->xSlicCurEventPtr += ((nextLpEvent->xSizeMinus1 +
LpEventAlign ) / LpEventAlign ) /
......
...@@ -144,7 +144,9 @@ struct ItLpNaca itLpNaca = { ...@@ -144,7 +144,9 @@ struct ItLpNaca itLpNaca = {
struct ItIplParmsReal xItIplParmsReal = {}; struct ItIplParmsReal xItIplParmsReal = {};
struct IoHriProcessorVpd xIoHriProcessorVpd[maxProcessors] = { #define maxPhysicalProcessors 32
struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = {
{ {
xInstCacheOperandSize: 32, xInstCacheOperandSize: 32,
xDataCacheOperandSize: 32, xDataCacheOperandSize: 32,
...@@ -172,7 +174,7 @@ struct ItVpdAreas itVpdAreas = { ...@@ -172,7 +174,7 @@ struct ItVpdAreas itVpdAreas = {
0, 0, 0, 0,
26, /* # VPD array entries */ 26, /* # VPD array entries */
10, /* # DMA array entries */ 10, /* # DMA array entries */
maxProcessors*2, maxProcessors, /* Max logical, physical procs */ maxProcessors*2, maxPhysicalProcessors, /* Max logical, physical procs */
offsetof(struct ItVpdAreas,xPlicDmaToks),/* offset to DMA toks */ offsetof(struct ItVpdAreas,xPlicDmaToks),/* offset to DMA toks */
offsetof(struct ItVpdAreas,xSlicVpdAdrs),/* offset to VPD addrs */ offsetof(struct ItVpdAreas,xSlicVpdAdrs),/* offset to VPD addrs */
offsetof(struct ItVpdAreas,xPlicDmaLens),/* offset to DMA lens */ offsetof(struct ItVpdAreas,xPlicDmaLens),/* offset to DMA lens */
......
...@@ -342,12 +342,15 @@ chrp_progress(char *s, unsigned short hex) ...@@ -342,12 +342,15 @@ chrp_progress(char *s, unsigned short hex)
extern void setup_default_decr(void); extern void setup_default_decr(void);
extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq;
void __init pSeries_calibrate_decr(void) void __init pSeries_calibrate_decr(void)
{ {
struct device_node *cpu; struct device_node *cpu;
struct div_result divres; struct div_result divres;
int *fp; int *fp;
unsigned long freq; unsigned long freq, processor_freq;
/* /*
* The cpu node should have a timebase-frequency property * The cpu node should have a timebase-frequency property
...@@ -360,8 +363,19 @@ void __init pSeries_calibrate_decr(void) ...@@ -360,8 +363,19 @@ void __init pSeries_calibrate_decr(void)
if (fp != 0) if (fp != 0)
freq = *fp; freq = *fp;
} }
ppc_tb_freq = freq;
processor_freq = freq;
if (cpu != 0) {
fp = (int *) get_property(cpu, "clock-frequency", NULL);
if (fp != 0)
processor_freq = *fp;
}
ppc_proc_freq = processor_freq;
printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
freq/1000000, freq%1000000 ); freq/1000000, freq%1000000 );
printk("time_init: processor frequency = %lu.%.6lu MHz\n",
processor_freq/1000000, processor_freq%1000000 );
tb_ticks_per_jiffy = freq / HZ; tb_ticks_per_jiffy = freq / HZ;
tb_ticks_per_sec = tb_ticks_per_jiffy * HZ; tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
......
...@@ -106,7 +106,7 @@ int __init iSeries_allocate_IRQ(HvBusNumber busNumber, HvSubBusNumber subBusNumb ...@@ -106,7 +106,7 @@ int __init iSeries_allocate_IRQ(HvBusNumber busNumber, HvSubBusNumber subBusNumb
{ {
u8 idsel = (deviceId >> 4); u8 idsel = (deviceId >> 4);
u8 function = deviceId & 0x0F; u8 function = deviceId & 0x0F;
int irq = ((((busNumber-1)*16 + (idsel-1)*8 + function)*9/8) % 254) + 1; int irq = ((((busNumber-1)*16 + (idsel-1)*8 + function)*9/8) % 253) + 2;
return irq; return irq;
} }
......
This diff is collapsed.
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/seq_file.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/machdep.h> #include <asm/machdep.h>
...@@ -587,6 +588,7 @@ static void __init build_iSeries_Memory_Map(void) ...@@ -587,6 +588,7 @@ static void __init build_iSeries_Memory_Map(void)
lmb_init(); lmb_init();
lmb_add( 0, naca->physicalMemorySize ); lmb_add( 0, naca->physicalMemorySize );
lmb_analyze(); /* ?? */
lmb_reserve( 0, __pa(klimit)); lmb_reserve( 0, __pa(klimit));
/* /*
...@@ -603,8 +605,10 @@ static void __init build_iSeries_Memory_Map(void) ...@@ -603,8 +605,10 @@ static void __init build_iSeries_Memory_Map(void)
static void __init setup_iSeries_cache_sizes(void) static void __init setup_iSeries_cache_sizes(void)
{ {
unsigned i,n; unsigned i,n;
naca->iCacheL1LineSize = xIoHriProcessorVpd[0].xInstCacheOperandSize; unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex;
naca->dCacheL1LineSize = xIoHriProcessorVpd[0].xDataCacheOperandSize;
naca->iCacheL1LineSize = xIoHriProcessorVpd[procIx].xInstCacheOperandSize;
naca->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize;
naca->iCacheL1LinesPerPage = PAGE_SIZE / naca->iCacheL1LineSize; naca->iCacheL1LinesPerPage = PAGE_SIZE / naca->iCacheL1LineSize;
naca->dCacheL1LinesPerPage = PAGE_SIZE / naca->dCacheL1LineSize; naca->dCacheL1LinesPerPage = PAGE_SIZE / naca->dCacheL1LineSize;
i = naca->iCacheL1LineSize; i = naca->iCacheL1LineSize;
...@@ -652,6 +656,9 @@ static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr) ...@@ -652,6 +656,9 @@ static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
} }
#endif /* CONFIG_PPC_ISERIES */ #endif /* CONFIG_PPC_ISERIES */
extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq;
/* /*
* Document me. * Document me.
*/ */
...@@ -659,6 +666,7 @@ void __init ...@@ -659,6 +666,7 @@ void __init
iSeries_setup_arch(void) iSeries_setup_arch(void)
{ {
void * eventStack; void * eventStack;
unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex;
/* Setup the Lp Event Queue */ /* Setup the Lp Event Queue */
...@@ -685,15 +693,19 @@ iSeries_setup_arch(void) ...@@ -685,15 +693,19 @@ iSeries_setup_arch(void)
xItLpQueue.xIndex = 0; xItLpQueue.xIndex = 0;
/* Compute processor frequency */ /* Compute processor frequency */
procFreqHz = (((1UL<<34) * 1000000) / xIoHriProcessorVpd[0].xProcFreq ); procFreqHz = (((1UL<<34) * 1000000) / xIoHriProcessorVpd[procIx].xProcFreq );
procFreqMhz = procFreqHz / 1000000; procFreqMhz = procFreqHz / 1000000;
procFreqMhzHundreths = (procFreqHz/10000) - (procFreqMhz*100); procFreqMhzHundreths = (procFreqHz/10000) - (procFreqMhz*100);
ppc_proc_freq = procFreqHz;
/* Compute time base frequency */ /* Compute time base frequency */
tbFreqHz = (((1UL<<32) * 1000000) / xIoHriProcessorVpd[0].xTimeBaseFreq ); tbFreqHz = (((1UL<<32) * 1000000) / xIoHriProcessorVpd[procIx].xTimeBaseFreq );
tbFreqMhz = tbFreqHz / 1000000; tbFreqMhz = tbFreqHz / 1000000;
tbFreqMhzHundreths = (tbFreqHz/10000) - (tbFreqMhz*100); tbFreqMhzHundreths = (tbFreqHz/10000) - (tbFreqMhz*100);
ppc_tb_freq = tbFreqHz;
printk("Max logical processors = %d\n", printk("Max logical processors = %d\n",
itVpdAreas.xSlicMaxLogicalProcs ); itVpdAreas.xSlicMaxLogicalProcs );
printk("Max physical processors = %d\n", printk("Max physical processors = %d\n",
...@@ -705,12 +717,12 @@ iSeries_setup_arch(void) ...@@ -705,12 +717,12 @@ iSeries_setup_arch(void)
tbFreqMhz, tbFreqMhz,
tbFreqMhzHundreths ); tbFreqMhzHundreths );
printk("Processor version = %x\n", printk("Processor version = %x\n",
xIoHriProcessorVpd[0].xPVR ); xIoHriProcessorVpd[procIx].xPVR );
} }
/* /*
* int iSeries_setup_residual() * int as400_setup_residual()
* *
* Description: * Description:
* This routine pretty-prints CPU information gathered from the VPD * This routine pretty-prints CPU information gathered from the VPD
...@@ -726,20 +738,25 @@ iSeries_setup_arch(void) ...@@ -726,20 +738,25 @@ iSeries_setup_arch(void)
* The number of bytes copied into 'buffer' if OK, otherwise zero or less * The number of bytes copied into 'buffer' if OK, otherwise zero or less
* on error. * on error.
*/ */
void void iSeries_setup_residual(struct seq_file *m)
iSeries_setup_residual(struct seq_file *m, unsigned long cpu_id)
{ {
seq_printf(m, "clock\t\t: %lu.%02luMhz\n", procFreqMhz,
procFreqMhzHundreths); seq_printf(m,"clock\t\t: %lu.%02luMhz\n",
seq_printf(m, "time base\t: %lu.%02luMHz\n", tbFreqMhz, procFreqMhz, procFreqMhzHundreths );
tbFreqMhzHundreths); seq_printf(m,"time base\t: %lu.%02luMHz\n",
seq_printf(m, "i-cache\t\t: %d\n", naca->iCacheL1LineSize); tbFreqMhz, tbFreqMhzHundreths );
seq_printf(m, "d-cache\t\t: %d\n", naca->dCacheL1LineSize); seq_printf(m,"i-cache\t\t: %d\n",
naca->iCacheL1LineSize);
seq_printf(m,"d-cache\t\t: %d\n",
naca->dCacheL1LineSize);
} }
void iSeries_get_cpuinfo(struct seq_file *m) void iSeries_get_cpuinfo(struct seq_file *m)
{ {
seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n");
seq_printf(m,"machine\t\t: 64-bit iSeries Logical Partition\n");
} }
/* /*
...@@ -805,9 +822,7 @@ extern void setup_default_decr(void); ...@@ -805,9 +822,7 @@ extern void setup_default_decr(void);
void __init void __init
iSeries_calibrate_decr(void) iSeries_calibrate_decr(void)
{ {
unsigned long freq;
unsigned long cyclesPerUsec; unsigned long cyclesPerUsec;
unsigned long tbf;
struct div_result divres; struct div_result divres;
...@@ -815,19 +830,21 @@ iSeries_calibrate_decr(void) ...@@ -815,19 +830,21 @@ iSeries_calibrate_decr(void)
* in cycles/sec * in cycles/sec
*/ */
tbf = xIoHriProcessorVpd[0].xTimeBaseFreq; cyclesPerUsec = ppc_tb_freq / 1000000; /* cycles / usec */
freq = 0x0100000000;
freq *= 1000000; /* 2^32 * 10^6 */
freq = freq / tbf; /* cycles / sec */
cyclesPerUsec = freq / 1000000; /* cycles / usec */
/* Set the amount to refresh the decrementer by. This /* Set the amount to refresh the decrementer by. This
* is the number of decrementer ticks it takes for * is the number of decrementer ticks it takes for
* 1/HZ seconds. * 1/HZ seconds.
*/ */
tb_ticks_per_jiffy = freq / HZ; tb_ticks_per_jiffy = ppc_tb_freq / HZ;
#if 0
/* TEST CODE FOR ADJTIME */
tb_ticks_per_jiffy += tb_ticks_per_jiffy / 5000;
/* END OF TEST CODE */
#endif
/* /*
* tb_ticks_per_sec = freq; would give better accuracy * tb_ticks_per_sec = freq; would give better accuracy
* but tb_ticks_per_sec = tb_ticks_per_jiffy*HZ; assures * but tb_ticks_per_sec = tb_ticks_per_jiffy*HZ; assures
...@@ -836,7 +853,7 @@ iSeries_calibrate_decr(void) ...@@ -836,7 +853,7 @@ iSeries_calibrate_decr(void)
*/ */
tb_ticks_per_sec = tb_ticks_per_jiffy * HZ; tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
tb_ticks_per_usec = cyclesPerUsec; tb_ticks_per_usec = cyclesPerUsec;
tb_to_us = mulhwu_scale_factor(freq, 1000000); tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres ); div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres );
tb_to_xs = divres.result_low; tb_to_xs = divres.result_low;
setup_default_decr(); setup_default_decr();
......
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#ifndef __ISERIES_SETUP_H__ #ifndef __ISERIES_SETUP_H__
#define __ISERIES_SETUP_H__ #define __ISERIES_SETUP_H__
#include <linux/seq_file.h>
extern void iSeries_init_early(void); extern void iSeries_init_early(void);
extern void iSeries_init(unsigned long r3, extern void iSeries_init(unsigned long r3,
unsigned long ird_start, unsigned long ird_start,
...@@ -28,8 +26,7 @@ extern void iSeries_init(unsigned long r3, ...@@ -28,8 +26,7 @@ extern void iSeries_init(unsigned long r3,
unsigned long cline_start, unsigned long cline_start,
unsigned long cline_end); unsigned long cline_end);
extern void iSeries_setup_arch(void); extern void iSeries_setup_arch(void);
extern void iSeries_setup_residual(struct seq_file *m, extern void iSeries_setup_residual(struct seq_file *m);
unsigned long cpu_id);
extern void iSeries_get_cpuinfo(struct seq_file *m); extern void iSeries_get_cpuinfo(struct seq_file *m);
extern void iSeries_init_IRQ(void); extern void iSeries_init_IRQ(void);
extern int iSeries_get_irq(struct pt_regs *regs); extern int iSeries_get_irq(struct pt_regs *regs);
......
...@@ -516,8 +516,7 @@ _GLOBAL(kernel_thread) ...@@ -516,8 +516,7 @@ _GLOBAL(kernel_thread)
#ifdef CONFIG_BINFMT_ELF32 #ifdef CONFIG_BINFMT_ELF32
/* Why isn't this a) automatic, b) written in 'C'? */ /* Why isn't this a) automatic, b) written in 'C'? */
.data .balign 8
.align 8
_GLOBAL(sys_call_table32) _GLOBAL(sys_call_table32)
.llong .sys_ni_syscall /* 0 - old "setup()" system call */ .llong .sys_ni_syscall /* 0 - old "setup()" system call */
.llong .sys32_exit .llong .sys32_exit
...@@ -544,7 +543,7 @@ _GLOBAL(sys_call_table32) ...@@ -544,7 +543,7 @@ _GLOBAL(sys_call_table32)
.llong .sys_oldumount .llong .sys_oldumount
.llong .sys_setuid .llong .sys_setuid
.llong .sys_getuid .llong .sys_getuid
.llong .ppc64_sys_stime /* 25 */ .llong .ppc64_sys32_stime /* 25 */
.llong .sys32_ptrace .llong .sys32_ptrace
.llong .sys_alarm .llong .sys_alarm
.llong .sys32_fstat .llong .sys32_fstat
...@@ -745,8 +744,8 @@ _GLOBAL(sys_call_table32) ...@@ -745,8 +744,8 @@ _GLOBAL(sys_call_table32)
.llong .sys_ni_syscall .llong .sys_ni_syscall
.endr .endr
#endif #endif
.data
.align 8 .balign 8
_GLOBAL(sys_call_table) _GLOBAL(sys_call_table)
.llong .sys_ni_syscall /* 0 - old "setup()" system call */ .llong .sys_ni_syscall /* 0 - old "setup()" system call */
.llong .sys_exit .llong .sys_exit
......
...@@ -782,10 +782,6 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, ...@@ -782,10 +782,6 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
} }
} }
/*
* Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
* lock.
*/
static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
int large, int local) int large, int local)
{ {
...@@ -801,10 +797,8 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, ...@@ -801,10 +797,8 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
avpn = vpn >> 11; avpn = vpn >> 11;
spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
lpar_rc = plpar_pte_remove(H_AVPN, slot, (vpn >> 4) & ~0x7fUL, &dummy1, lpar_rc = plpar_pte_remove(H_AVPN, slot, (vpn >> 4) & ~0x7fUL, &dummy1,
&dummy2); &dummy2);
spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
if (lpar_rc == H_Not_Found) { if (lpar_rc == H_Not_Found) {
udbg_printf("invalidate missed\n"); udbg_printf("invalidate missed\n");
...@@ -846,4 +840,5 @@ void pSeries_lpar_mm_init(void) ...@@ -846,4 +840,5 @@ void pSeries_lpar_mm_init(void)
ppc_md.insert_hpte = pSeries_lpar_insert_hpte; ppc_md.insert_hpte = pSeries_lpar_insert_hpte;
ppc_md.remove_hpte = pSeries_lpar_remove_hpte; ppc_md.remove_hpte = pSeries_lpar_remove_hpte;
ppc_md.make_pte = pSeries_lpar_make_pte; ppc_md.make_pte = pSeries_lpar_make_pte;
ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
} }
...@@ -277,6 +277,9 @@ void machine_halt(void) ...@@ -277,6 +277,9 @@ void machine_halt(void)
ppc_md.halt(); ppc_md.halt();
} }
unsigned long ppc_proc_freq;
unsigned long ppc_tb_freq;
static int show_cpuinfo(struct seq_file *m, void *v) static int show_cpuinfo(struct seq_file *m, void *v)
{ {
unsigned long cpu_id = (unsigned long)v - 1; unsigned long cpu_id = (unsigned long)v - 1;
...@@ -286,10 +289,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -286,10 +289,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (cpu_id == NR_CPUS) { if (cpu_id == NR_CPUS) {
unsigned long bogosum = smp_num_cpus * loops_per_jiffy;
seq_printf(m, "total bogomips\t: %lu.%02lu\n",
bogosum/(500000/HZ),
bogosum/(5000/HZ) % 100);
if (ppc_md.get_cpuinfo != NULL) if (ppc_md.get_cpuinfo != NULL)
ppc_md.get_cpuinfo(m); ppc_md.get_cpuinfo(m);
...@@ -357,10 +356,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -357,10 +356,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "revision\t: %hd.%hd\n", maj, min); seq_printf(m, "revision\t: %hd.%hd\n", maj, min);
seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
loops_per_jiffy/(500000/HZ),
loops_per_jiffy/(5000/HZ) % 100);
return 0; return 0;
} }
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include <asm/nvram.h> #include <asm/nvram.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/init.h>
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
#include <asm/iSeries/HvCallXm.h> #include <asm/iSeries/HvCallXm.h>
#endif #endif
...@@ -83,6 +84,7 @@ unsigned long next_xtime_sync_tb; ...@@ -83,6 +84,7 @@ unsigned long next_xtime_sync_tb;
unsigned long xtime_sync_interval; unsigned long xtime_sync_interval;
unsigned long tb_to_xs; unsigned long tb_to_xs;
unsigned tb_to_us; unsigned tb_to_us;
unsigned long processor_freq;
spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
struct gettimeofday_struct do_gtod; struct gettimeofday_struct do_gtod;
...@@ -97,6 +99,10 @@ extern unsigned long prof_len; ...@@ -97,6 +99,10 @@ extern unsigned long prof_len;
extern unsigned long prof_shift; extern unsigned long prof_shift;
extern char _stext; extern char _stext;
void ppc_adjtimex(void);
static unsigned adjusting_time = 0;
static inline void ppc_do_profile (unsigned long nip) static inline void ppc_do_profile (unsigned long nip)
{ {
if (!prof_buffer) if (!prof_buffer)
...@@ -269,6 +275,8 @@ int timer_interrupt(struct pt_regs * regs) ...@@ -269,6 +275,8 @@ int timer_interrupt(struct pt_regs * regs)
timer_sync_xtime( cur_tb ); timer_sync_xtime( cur_tb );
timer_check_rtc(); timer_check_rtc();
write_unlock(&xtime_lock); write_unlock(&xtime_lock);
if ( adjusting_time && (time_adjust == 0) )
ppc_adjtimex();
} }
paca->next_jiffy_update_tb += tb_ticks_per_jiffy; paca->next_jiffy_update_tb += tb_ticks_per_jiffy;
} }
...@@ -386,13 +394,35 @@ void do_settimeofday(struct timeval *tv) ...@@ -386,13 +394,35 @@ void do_settimeofday(struct timeval *tv)
* fields itself. This way, the fields which are used for * fields itself. This way, the fields which are used for
* do_settimeofday get updated too. * do_settimeofday get updated too.
*/ */
long ppc64_sys32_stime(int* tptr)
long ppc64_sys_stime(int * tptr)
{ {
int value; int value;
struct timeval myTimeval; struct timeval myTimeval;
PPCDBG(PPCDBG_SYS32, "ppc64_sys_stime - entered - tptr=%p, *tptr=0x%x \n", tptr, *tptr); if (!capable(CAP_SYS_TIME))
return -EPERM;
if (get_user(value, tptr))
return -EFAULT;
myTimeval.tv_sec = value;
myTimeval.tv_usec = 0;
do_settimeofday(&myTimeval);
return 0;
}
/*
* This function is a copy of the architecture independent function
* but which calls do_settimeofday rather than setting the xtime
* fields itself. This way, the fields which are used for
* do_settimeofday get updated too.
*/
long ppc64_sys_stime(long* tptr)
{
long value;
struct timeval myTimeval;
if (!capable(CAP_SYS_TIME)) if (!capable(CAP_SYS_TIME))
return -EPERM; return -EPERM;
...@@ -405,7 +435,6 @@ long ppc64_sys_stime(int * tptr) ...@@ -405,7 +435,6 @@ long ppc64_sys_stime(int * tptr)
do_settimeofday(&myTimeval); do_settimeofday(&myTimeval);
PPCDBG(PPCDBG_SYS32, "ppc64_sys_stime - exiting w/ 0 \n");
return 0; return 0;
} }
...@@ -426,6 +455,7 @@ void __init time_init(void) ...@@ -426,6 +455,7 @@ void __init time_init(void)
tb_last_stamp = get_tb(); tb_last_stamp = get_tb();
do_gtod.tb_orig_stamp = tb_last_stamp; do_gtod.tb_orig_stamp = tb_last_stamp;
do_gtod.varp = &do_gtod.vars[0]; do_gtod.varp = &do_gtod.vars[0];
do_gtod.var_idx = 0;
do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
do_gtod.varp->tb_to_xs = tb_to_xs; do_gtod.varp->tb_to_xs = tb_to_xs;
...@@ -434,6 +464,8 @@ void __init time_init(void) ...@@ -434,6 +464,8 @@ void __init time_init(void)
xtime_sync_interval = tb_ticks_per_sec - (tb_ticks_per_sec/8); xtime_sync_interval = tb_ticks_per_sec - (tb_ticks_per_sec/8);
next_xtime_sync_tb = tb_last_stamp + xtime_sync_interval; next_xtime_sync_tb = tb_last_stamp + xtime_sync_interval;
time_freq = 0;
xtime.tv_usec = 0; xtime.tv_usec = 0;
last_rtc_update = xtime.tv_sec; last_rtc_update = xtime.tv_sec;
write_unlock_irqrestore(&xtime_lock, flags); write_unlock_irqrestore(&xtime_lock, flags);
...@@ -452,10 +484,12 @@ void __init time_init(void) ...@@ -452,10 +484,12 @@ void __init time_init(void)
* to microseconds to keep do_gettimeofday synchronized * to microseconds to keep do_gettimeofday synchronized
* with ntpd. * with ntpd.
* Use the time_freq and time_offset computed by adjtimex to * Use the time_adjust, time_freq and time_offset computed by adjtimex to
* adjust the frequency. * adjust the frequency.
*/ */
/* #define DEBUG_PPC_ADJTIMEX 1 */
void ppc_adjtimex(void) void ppc_adjtimex(void)
{ {
unsigned long den, new_tb_ticks_per_sec, tb_ticks, old_xsec, new_tb_to_xs, new_xsec, new_stamp_xsec; unsigned long den, new_tb_ticks_per_sec, tb_ticks, old_xsec, new_tb_to_xs, new_xsec, new_stamp_xsec;
...@@ -464,7 +498,12 @@ void ppc_adjtimex(void) ...@@ -464,7 +498,12 @@ void ppc_adjtimex(void)
struct div_result divres; struct div_result divres;
unsigned long flags; unsigned long flags;
struct gettimeofday_vars * temp_varp; struct gettimeofday_vars * temp_varp;
unsigned temp_idx;
long singleshot_ppm = 0;
/* Compute parts per million frequency adjustment to accomplish the time adjustment
implied by time_offset to be applied over the elapsed time indicated by time_constant.
Use SHIFT_USEC to get it into the same units as time_freq. */
if ( time_offset < 0 ) { if ( time_offset < 0 ) {
ltemp = -time_offset; ltemp = -time_offset;
ltemp <<= SHIFT_USEC - SHIFT_UPDATE; ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
...@@ -476,8 +515,40 @@ void ppc_adjtimex(void) ...@@ -476,8 +515,40 @@ void ppc_adjtimex(void)
ltemp <<= SHIFT_USEC - SHIFT_UPDATE; ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
ltemp >>= SHIFT_KG + time_constant; ltemp >>= SHIFT_KG + time_constant;
} }
delta_freq = time_freq + ltemp;
/* If there is a single shot time adjustment in progress */
if ( time_adjust ) {
#ifdef DEBUG_PPC_ADJTIMEX
printk("ppc_adjtimex: ");
if ( adjusting_time == 0 )
printk("starting ");
printk("single shot time_adjust = %ld\n", time_adjust);
#endif
adjusting_time = 1;
/* Compute parts per million frequency adjustment to match time_adjust */
singleshot_ppm = tickadj * HZ;
/* The adjustment should be tickadj*HZ to match the code in linux/kernel/timer.c, but
experiments show that this is too large. 3/4 of tickadj*HZ seems about right */
singleshot_ppm -= singleshot_ppm / 4;
/* Use SHIFT_USEC to get it into the same units as time_freq */
singleshot_ppm <<= SHIFT_USEC;
if ( time_adjust < 0 )
singleshot_ppm = -singleshot_ppm;
}
else {
#ifdef DEBUG_PPC_ADJTIMEX
if ( adjusting_time )
printk("ppc_adjtimex: ending single shot time_adjust\n");
#endif
adjusting_time = 0;
}
/* Add up all of the frequency adjustments */
delta_freq = time_freq + ltemp + singleshot_ppm;
/* Compute a new value for tb_ticks_per_sec based on the frequency adjustment */
den = 1000000 * (1 << (SHIFT_USEC - 8)); den = 1000000 * (1 << (SHIFT_USEC - 8));
if ( delta_freq < 0 ) { if ( delta_freq < 0 ) {
tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( (-delta_freq) >> (SHIFT_USEC - 8))) / den; tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( (-delta_freq) >> (SHIFT_USEC - 8))) / den;
...@@ -487,6 +558,16 @@ void ppc_adjtimex(void) ...@@ -487,6 +558,16 @@ void ppc_adjtimex(void)
tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( delta_freq >> (SHIFT_USEC - 8))) / den; tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( delta_freq >> (SHIFT_USEC - 8))) / den;
new_tb_ticks_per_sec = tb_ticks_per_sec - tb_ticks_per_sec_delta; new_tb_ticks_per_sec = tb_ticks_per_sec - tb_ticks_per_sec_delta;
} }
#ifdef DEBUG_PPC_ADJTIMEX
printk("ppc_adjtimex: ltemp = %ld, time_freq = %ld, singleshot_ppm = %ld\n", ltemp, time_freq, singleshot_ppm);
printk("ppc_adjtimex: tb_ticks_per_sec - base = %ld new = %ld\n", tb_ticks_per_sec, new_tb_ticks_per_sec);
#endif
/* Compute a new value of tb_to_xs (used to convert tb to microseconds and a new value of
stamp_xsec which is the time (in 1/2^20 second units) corresponding to tb_orig_stamp. This
new value of stamp_xsec compensates for the change in frequency (implied by the new tb_to_xs)
which guarantees that the current time remains the same */
tb_ticks = get_tb() - do_gtod.tb_orig_stamp; tb_ticks = get_tb() - do_gtod.tb_orig_stamp;
div128_by_32( 1024*1024, 0, new_tb_ticks_per_sec, &divres ); div128_by_32( 1024*1024, 0, new_tb_ticks_per_sec, &divres );
new_tb_to_xs = divres.result_low; new_tb_to_xs = divres.result_low;
...@@ -496,14 +577,23 @@ void ppc_adjtimex(void) ...@@ -496,14 +577,23 @@ void ppc_adjtimex(void)
old_xsec = mulhdu( tb_ticks, do_gtod.varp->tb_to_xs ); old_xsec = mulhdu( tb_ticks, do_gtod.varp->tb_to_xs );
new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec; new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec;
if (do_gtod.varp == &do_gtod.vars[0]) /* There are two copies of tb_to_xs and stamp_xsec so that no lock is needed to access and use these
values in do_gettimeofday. We alternate the copies and as long as a reasonable time elapses between
changes, there will never be inconsistent values. ntpd has a minimum of one minute between updates */
if (do_gtod.var_idx == 0) {
temp_varp = &do_gtod.vars[1]; temp_varp = &do_gtod.vars[1];
else temp_idx = 1;
}
else {
temp_varp = &do_gtod.vars[0]; temp_varp = &do_gtod.vars[0];
temp_idx = 0;
}
temp_varp->tb_to_xs = new_tb_to_xs; temp_varp->tb_to_xs = new_tb_to_xs;
temp_varp->stamp_xsec = new_stamp_xsec; temp_varp->stamp_xsec = new_stamp_xsec;
mb(); mb();
do_gtod.varp = temp_varp; do_gtod.varp = temp_varp;
do_gtod.var_idx = temp_idx;
write_unlock_irqrestore( &xtime_lock, flags ); write_unlock_irqrestore( &xtime_lock, flags );
......
...@@ -262,8 +262,10 @@ static int find_tb_table(unsigned long codeaddr, struct tbtable *tab); ...@@ -262,8 +262,10 @@ static int find_tb_table(unsigned long codeaddr, struct tbtable *tab);
static inline void disable_surveillance(void) static inline void disable_surveillance(void)
{ {
#ifndef CONFIG_PPC_ISERIES
rtas_call(rtas_token("set-indicator"), 3, 1, NULL, SURVEILLANCE_TOKEN, rtas_call(rtas_token("set-indicator"), 3, 1, NULL, SURVEILLANCE_TOKEN,
0, 0); 0, 0);
#endif
} }
void void
......
...@@ -97,6 +97,8 @@ struct HvCallPci_BridgeInfo { ...@@ -97,6 +97,8 @@ struct HvCallPci_BridgeInfo {
struct HvCallPci_BusUnitInfo busUnitInfo; // Generic bus unit info struct HvCallPci_BusUnitInfo busUnitInfo; // Generic bus unit info
u8 subBusNumber; // Bus number of secondary bus u8 subBusNumber; // Bus number of secondary bus
u8 maxAgents; // Max idsels on secondary bus u8 maxAgents; // Max idsels on secondary bus
u8 maxSubBusNumber; // Max Sub Bus
u8 logicalSlotNumber; // Logical Slot Number for IOA
}; };
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
extern unsigned long reloc_offset(void); extern unsigned long reloc_offset(void);
#define MAX_LMB_REGIONS 32 #define MAX_LMB_REGIONS 64
union lmb_reg_property { union lmb_reg_property {
struct reg_property32 addr32[MAX_LMB_REGIONS]; struct reg_property32 addr32[MAX_LMB_REGIONS];
......
...@@ -50,6 +50,7 @@ struct gettimeofday_struct { ...@@ -50,6 +50,7 @@ struct gettimeofday_struct {
unsigned long tb_ticks_per_sec; unsigned long tb_ticks_per_sec;
struct gettimeofday_vars vars[2]; struct gettimeofday_vars vars[2];
struct gettimeofday_vars * volatile varp; struct gettimeofday_vars * volatile varp;
unsigned var_idx;
unsigned tb_to_us; unsigned tb_to_us;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment