Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
768b6efa
Commit
768b6efa
authored
May 19, 2003
by
David Mosberger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ia64: Update for new time_interpolator infrastructure.
parent
854631be
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
55 additions
and
72 deletions
+55
-72
arch/ia64/Kconfig
arch/ia64/Kconfig
+4
-0
arch/ia64/kernel/time.c
arch/ia64/kernel/time.c
+34
-32
arch/ia64/sn/kernel/sn2/timer.c
arch/ia64/sn/kernel/sn2/timer.c
+17
-40
No files found.
arch/ia64/Kconfig
View file @
768b6efa
...
@@ -26,6 +26,10 @@ config RWSEM_XCHGADD_ALGORITHM
...
@@ -26,6 +26,10 @@ config RWSEM_XCHGADD_ALGORITHM
bool
bool
default y
default y
config TIME_INTERPOLATION
bool
default y
choice
choice
prompt "IA-64 processor type"
prompt "IA-64 processor type"
default ITANIUM
default ITANIUM
...
...
arch/ia64/kernel/time.c
View file @
768b6efa
...
@@ -26,10 +26,6 @@
...
@@ -26,10 +26,6 @@
#include <asm/system.h>
#include <asm/system.h>
extern
unsigned
long
wall_jiffies
;
extern
unsigned
long
wall_jiffies
;
unsigned
long
last_nsec_offset
;
static
unsigned
long
ia64_gettimeoffset
(
void
);
unsigned
long
(
*
gettimeoffset
)(
void
)
=
&
ia64_gettimeoffset
;
u64
jiffies_64
=
INITIAL_JIFFIES
;
u64
jiffies_64
=
INITIAL_JIFFIES
;
...
@@ -65,30 +61,18 @@ do_profile (unsigned long ip)
...
@@ -65,30 +61,18 @@ do_profile (unsigned long ip)
atomic_inc
((
atomic_t
*
)
&
prof_buffer
[
ip
]);
atomic_inc
((
atomic_t
*
)
&
prof_buffer
[
ip
]);
}
}
void
static
void
i
a64_reset_wall_time
(
void
)
i
tc_reset
(
void
)
{
{
last_nsec_offset
=
0
;
}
}
/*
/*
* Adjust for the fact that xtime has been advanced by delta_nsec (may be negative and/or
* Adjust for the fact that xtime has been advanced by delta_nsec (may be negative and/or
* larger than NSEC_PER_SEC.
* larger than NSEC_PER_SEC.
*/
*/
void
static
void
i
a64_update_wall_tim
e
(
long
delta_nsec
)
i
tc_updat
e
(
long
delta_nsec
)
{
{
if
(
last_nsec_offset
>
0
)
{
unsigned
long
new
,
old
;
do
{
old
=
last_nsec_offset
;
if
(
old
>
delta_nsec
)
new
=
old
-
delta_nsec
;
else
new
=
0
;
}
while
(
cmpxchg
(
&
last_nsec_offset
,
old
,
new
)
!=
old
);
}
}
}
/*
/*
...
@@ -96,7 +80,7 @@ ia64_update_wall_time (long delta_nsec)
...
@@ -96,7 +80,7 @@ ia64_update_wall_time (long delta_nsec)
* xtime_lock must be at least read-locked when calling this routine.
* xtime_lock must be at least read-locked when calling this routine.
*/
*/
unsigned
long
unsigned
long
i
a64_gettime
offset
(
void
)
i
tc_get_
offset
(
void
)
{
{
unsigned
long
elapsed_cycles
,
lost
=
jiffies
-
wall_jiffies
;
unsigned
long
elapsed_cycles
,
lost
=
jiffies
-
wall_jiffies
;
unsigned
long
now
,
last_tick
;
unsigned
long
now
,
last_tick
;
...
@@ -114,6 +98,12 @@ ia64_gettimeoffset (void)
...
@@ -114,6 +98,12 @@ ia64_gettimeoffset (void)
return
(
elapsed_cycles
*
local_cpu_data
->
nsec_per_cyc
)
>>
IA64_NSEC_PER_CYC_SHIFT
;
return
(
elapsed_cycles
*
local_cpu_data
->
nsec_per_cyc
)
>>
IA64_NSEC_PER_CYC_SHIFT
;
}
}
static
struct
time_interpolator
itc_interpolator
=
{
.
get_offset
=
itc_get_offset
,
.
update
=
itc_update
,
.
reset
=
itc_reset
};
static
inline
void
static
inline
void
set_normalized_timespec
(
struct
timespec
*
ts
,
time_t
sec
,
long
nsec
)
set_normalized_timespec
(
struct
timespec
*
ts
,
time_t
sec
,
long
nsec
)
{
{
...
@@ -143,7 +133,7 @@ do_settimeofday (struct timeval *tv)
...
@@ -143,7 +133,7 @@ do_settimeofday (struct timeval *tv)
* Discover what correction gettimeofday would have done, and then undo
* Discover what correction gettimeofday would have done, and then undo
* it!
* it!
*/
*/
nsec
-=
(
*
gettimeoffset
)
();
nsec
-=
time_interpolator_get_offset
();
wtm_sec
=
wall_to_monotonic
.
tv_sec
+
(
xtime
.
tv_sec
-
sec
);
wtm_sec
=
wall_to_monotonic
.
tv_sec
+
(
xtime
.
tv_sec
-
sec
);
wtm_nsec
=
wall_to_monotonic
.
tv_nsec
+
(
xtime
.
tv_nsec
-
nsec
);
wtm_nsec
=
wall_to_monotonic
.
tv_nsec
+
(
xtime
.
tv_nsec
-
nsec
);
...
@@ -155,7 +145,7 @@ do_settimeofday (struct timeval *tv)
...
@@ -155,7 +145,7 @@ do_settimeofday (struct timeval *tv)
time_status
|=
STA_UNSYNC
;
time_status
|=
STA_UNSYNC
;
time_maxerror
=
NTP_PHASE_LIMIT
;
time_maxerror
=
NTP_PHASE_LIMIT
;
time_esterror
=
NTP_PHASE_LIMIT
;
time_esterror
=
NTP_PHASE_LIMIT
;
(
*
reset_wall_time_hook
)
();
time_interpolator_reset
();
}
}
write_sequnlock_irq
(
&
xtime_lock
);
write_sequnlock_irq
(
&
xtime_lock
);
clock_was_set
();
clock_was_set
();
...
@@ -170,7 +160,7 @@ do_gettimeofday (struct timeval *tv)
...
@@ -170,7 +160,7 @@ do_gettimeofday (struct timeval *tv)
seq
=
read_seqbegin
(
&
xtime_lock
);
seq
=
read_seqbegin
(
&
xtime_lock
);
{
{
old
=
last_nsec_offset
;
old
=
last_nsec_offset
;
offset
=
(
*
gettimeoffset
)
();
offset
=
time_interpolator_get_offset
();
sec
=
xtime
.
tv_sec
;
sec
=
xtime
.
tv_sec
;
nsec
=
xtime
.
tv_nsec
;
nsec
=
xtime
.
tv_nsec
;
}
}
...
@@ -308,16 +298,17 @@ ia64_cpu_local_tick (void)
...
@@ -308,16 +298,17 @@ ia64_cpu_local_tick (void)
void
__init
void
__init
ia64_init_itm
(
void
)
ia64_init_itm
(
void
)
{
{
unsigned
long
platform_base_freq
,
itc_freq
,
drift
;
unsigned
long
platform_base_freq
,
itc_freq
;
struct
pal_freq_ratio
itc_ratio
,
proc_ratio
;
struct
pal_freq_ratio
itc_ratio
,
proc_ratio
;
long
status
;
long
status
,
platform_base_drift
,
itc_drift
;
/*
/*
* According to SAL v2.6, we need to use a SAL call to determine the platform base
* According to SAL v2.6, we need to use a SAL call to determine the platform base
* frequency and then a PAL call to determine the frequency ratio between the ITC
* frequency and then a PAL call to determine the frequency ratio between the ITC
* and the base frequency.
* and the base frequency.
*/
*/
status
=
ia64_sal_freq_base
(
SAL_FREQ_BASE_PLATFORM
,
&
platform_base_freq
,
&
drift
);
status
=
ia64_sal_freq_base
(
SAL_FREQ_BASE_PLATFORM
,
&
platform_base_freq
,
&
platform_base_drift
);
if
(
status
!=
0
)
{
if
(
status
!=
0
)
{
printk
(
KERN_ERR
"SAL_FREQ_BASE_PLATFORM failed: %s
\n
"
,
ia64_sal_strerror
(
status
));
printk
(
KERN_ERR
"SAL_FREQ_BASE_PLATFORM failed: %s
\n
"
,
ia64_sal_strerror
(
status
));
}
else
{
}
else
{
...
@@ -330,6 +321,7 @@ ia64_init_itm (void)
...
@@ -330,6 +321,7 @@ ia64_init_itm (void)
printk
(
KERN_ERR
printk
(
KERN_ERR
"SAL/PAL failed to obtain frequency info---inventing reasonable values
\n
"
);
"SAL/PAL failed to obtain frequency info---inventing reasonable values
\n
"
);
platform_base_freq
=
100000000
;
platform_base_freq
=
100000000
;
platform_base_drift
=
-
1
;
/* no drift info */
itc_ratio
.
num
=
3
;
itc_ratio
.
num
=
3
;
itc_ratio
.
den
=
1
;
itc_ratio
.
den
=
1
;
}
}
...
@@ -337,6 +329,7 @@ ia64_init_itm (void)
...
@@ -337,6 +329,7 @@ ia64_init_itm (void)
printk
(
KERN_ERR
"Platform base frequency %lu bogus---resetting to 75MHz!
\n
"
,
printk
(
KERN_ERR
"Platform base frequency %lu bogus---resetting to 75MHz!
\n
"
,
platform_base_freq
);
platform_base_freq
);
platform_base_freq
=
75000000
;
platform_base_freq
=
75000000
;
platform_base_drift
=
-
1
;
}
}
if
(
!
proc_ratio
.
den
)
if
(
!
proc_ratio
.
den
)
proc_ratio
.
den
=
1
;
/* avoid division by zero */
proc_ratio
.
den
=
1
;
/* avoid division by zero */
...
@@ -344,11 +337,17 @@ ia64_init_itm (void)
...
@@ -344,11 +337,17 @@ ia64_init_itm (void)
itc_ratio
.
den
=
1
;
/* avoid division by zero */
itc_ratio
.
den
=
1
;
/* avoid division by zero */
itc_freq
=
(
platform_base_freq
*
itc_ratio
.
num
)
/
itc_ratio
.
den
;
itc_freq
=
(
platform_base_freq
*
itc_ratio
.
num
)
/
itc_ratio
.
den
;
if
(
platform_base_drift
!=
-
1
)
itc_drift
=
platform_base_drift
*
itc_ratio
.
num
/
itc_ratio
.
den
;
else
itc_drift
=
-
1
;
local_cpu_data
->
itm_delta
=
(
itc_freq
+
HZ
/
2
)
/
HZ
;
local_cpu_data
->
itm_delta
=
(
itc_freq
+
HZ
/
2
)
/
HZ
;
printk
(
KERN_INFO
"CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, "
printk
(
KERN_INFO
"CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, "
"ITC freq=%lu.%03luMHz
\n
"
,
smp_processor_id
(),
"ITC freq=%lu.%03luMHz
+/-%ldppm
\n
"
,
smp_processor_id
(),
platform_base_freq
/
1000000
,
(
platform_base_freq
/
1000
)
%
1000
,
platform_base_freq
/
1000000
,
(
platform_base_freq
/
1000
)
%
1000
,
itc_ratio
.
num
,
itc_ratio
.
den
,
itc_freq
/
1000000
,
(
itc_freq
/
1000
)
%
1000
);
itc_ratio
.
num
,
itc_ratio
.
den
,
itc_freq
/
1000000
,
(
itc_freq
/
1000
)
%
1000
,
itc_drift
);
local_cpu_data
->
proc_freq
=
(
platform_base_freq
*
proc_ratio
.
num
)
/
proc_ratio
.
den
;
local_cpu_data
->
proc_freq
=
(
platform_base_freq
*
proc_ratio
.
num
)
/
proc_ratio
.
den
;
local_cpu_data
->
itc_freq
=
itc_freq
;
local_cpu_data
->
itc_freq
=
itc_freq
;
...
@@ -356,6 +355,12 @@ ia64_init_itm (void)
...
@@ -356,6 +355,12 @@ ia64_init_itm (void)
local_cpu_data
->
nsec_per_cyc
=
((
NSEC_PER_SEC
<<
IA64_NSEC_PER_CYC_SHIFT
)
local_cpu_data
->
nsec_per_cyc
=
((
NSEC_PER_SEC
<<
IA64_NSEC_PER_CYC_SHIFT
)
+
itc_freq
/
2
)
/
itc_freq
;
+
itc_freq
/
2
)
/
itc_freq
;
if
(
!
(
sal_platform_features
&
IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT
))
{
itc_interpolator
.
frequency
=
local_cpu_data
->
itc_freq
;
itc_interpolator
.
drift
=
itc_drift
;
register_time_interpolator
(
&
itc_interpolator
);
}
/* Setup the CPU local timer tick */
/* Setup the CPU local timer tick */
ia64_cpu_local_tick
();
ia64_cpu_local_tick
();
}
}
...
@@ -369,9 +374,6 @@ static struct irqaction timer_irqaction = {
...
@@ -369,9 +374,6 @@ static struct irqaction timer_irqaction = {
void
__init
void
__init
time_init
(
void
)
time_init
(
void
)
{
{
update_wall_time_hook
=
ia64_update_wall_time
;
reset_wall_time_hook
=
ia64_reset_wall_time
;
register_percpu_irq
(
IA64_TIMER_VECTOR
,
&
timer_irqaction
);
register_percpu_irq
(
IA64_TIMER_VECTOR
,
&
timer_irqaction
);
efi_gettimeofday
(
&
xtime
);
efi_gettimeofday
(
&
xtime
);
ia64_init_itm
();
ia64_init_itm
();
...
...
arch/ia64/sn/kernel/sn2/timer.c
View file @
768b6efa
...
@@ -20,68 +20,45 @@
...
@@ -20,68 +20,45 @@
extern
unsigned
long
sn_rtc_cycles_per_second
;
extern
unsigned
long
sn_rtc_cycles_per_second
;
static
volatile
unsigned
long
last_wall_rtc
;
static
volatile
unsigned
long
last_wall_rtc
;
/**
* gettimeoffset - number of nsecs elapsed since &xtime was last updated
*
* This function is used by do_gettimeofday() to determine the number
* of nsecs that have elapsed since the last update to &xtime. On SN
* this is accomplished using the RTC built in to each Hub chip; each
* is guaranteed to be synchronized by the PROM, so a local read will
* suffice (GET_RTC_COUNTER() does this for us). A snapshot of the RTC
* value is taken every time wall_jiffies is updated by the
* update_wall_time_hook (sn2_update_wall_time) which means we don't
* have to adjust for lost jiffies ticks or anything like that.
*/
static
volatile
long
rtc_offset
;
static
long
rtc_nsecs_per_cycle
;
static
long
rtc_nsecs_per_cycle
;
static
long
rtc_per_timer_tick
;
static
long
rtc_per_timer_tick
;
unsigned
long
static
unsigned
long
sn_gettime
offset
(
void
)
get
offset
(
void
)
{
{
long
current_rtc
,
elapsed_rtc
,
old
,
new_offset
;
return
(
long
)
(
GET_RTC_COUNTER
()
-
last_wall_rtc
)
*
rtc_nsecs_per_cycle
;
do
{
old
=
rtc_offset
;
current_rtc
=
GET_RTC_COUNTER
();
/*
* Need to address wrapping here!
*/
elapsed_rtc
=
(
long
)(
current_rtc
-
last_wall_rtc
);
new_offset
=
max
(
elapsed_rtc
,
old
);
}
while
(
cmpxchg
(
&
rtc_offset
,
old
,
new_offset
)
!=
old
);
return
new_offset
*
rtc_nsecs_per_cycle
;
}
}
void
sn2_update_wall_time
(
long
delta_nsec
)
static
void
update
(
long
delta_nsec
)
{
{
ia64_update_wall_time
(
delta_nsec
);
rtc_offset
-=
min
(
rtc_offset
,
rtc_per_timer_tick
);
last_wall_rtc
=
GET_RTC_COUNTER
();
last_wall_rtc
=
GET_RTC_COUNTER
();
}
}
void
sn2_reset_wall_time
(
void
)
static
void
reset
(
void
)
{
{
ia64_reset_wall_time
();
rtc_offset
=
0
;
last_wall_rtc
=
GET_RTC_COUNTER
();
last_wall_rtc
=
GET_RTC_COUNTER
();
}
}
static
struct
time_interpolator
sn2_interpolator
=
{
.
get_offset
=
getoffset
,
.
update
=
update
,
.
reset
=
reset
};
void
__init
void
__init
sn_timer_init
(
void
)
sn_timer_init
(
void
)
{
{
sn2_interpolator
.
frequency
=
sn_rtc_cycles_per_second
;
sn2_interpolator
.
drift
=
-
1
;
/* unknown */
register_time_interpolator
(
&
sn2_interpolator
);
rtc_per_timer_tick
=
sn_rtc_cycles_per_second
/
HZ
;
rtc_per_timer_tick
=
sn_rtc_cycles_per_second
/
HZ
;
rtc_nsecs_per_cycle
=
1000000000
/
sn_rtc_cycles_per_second
;
rtc_nsecs_per_cycle
=
1000000000
/
sn_rtc_cycles_per_second
;
last_wall_rtc
=
GET_RTC_COUNTER
();
last_wall_rtc
=
GET_RTC_COUNTER
();
update_wall_time_hook
=
sn2_update_wall_time
;
reset_wall_time_hook
=
sn2_reset_wall_time
;
gettimeoffset
=
sn_gettimeoffset
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment