Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
df080e7c
Commit
df080e7c
authored
Feb 02, 2006
by
Tony Luck
Browse files
Options
Browse Files
Download
Plain Diff
Pull update-tlbflush-sn into release branch
parents
0271fc2d
61a34a02
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
75 additions
and
121 deletions
+75
-121
arch/ia64/sn/kernel/sn2/sn2_smp.c
arch/ia64/sn/kernel/sn2/sn2_smp.c
+75
-121
No files found.
arch/ia64/sn/kernel/sn2/sn2_smp.c
View file @
df080e7c
...
...
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000-200
5
Silicon Graphics, Inc. All rights reserved.
* Copyright (C) 2000-200
6
Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/init.h>
...
...
@@ -46,104 +46,28 @@ DECLARE_PER_CPU(struct ptc_stats, ptcstats);
static
__cacheline_aligned
DEFINE_SPINLOCK
(
sn2_global_ptc_lock
);
void
sn2_ptc_deadlock_recovery
(
short
*
,
short
,
int
,
volatile
unsigned
long
*
,
unsigned
long
data0
,
volatile
unsigned
long
*
,
unsigned
long
data1
);
void
sn2_ptc_deadlock_recovery
(
short
*
,
short
,
short
,
int
,
volatile
unsigned
long
*
,
unsigned
long
,
volatile
unsigned
long
*
,
unsigned
long
);
#ifdef DEBUG_PTC
/*
* ptctest:
*
* xyz - 3 digit hex number:
* x - Force PTC purges to use shub:
* 0 - no force
* 1 - force
* y - interupt enable
* 0 - disable interrupts
* 1 - leave interuupts enabled
* z - type of lock:
* 0 - global lock
* 1 - node local lock
* 2 - no lock
*
* Note: on shub1, only ptctest == 0 is supported. Don't try other values!
* Note: some is the following is captured here to make degugging easier
* (the macros make more sense if you see the debug patch - not posted)
*/
static
unsigned
int
sn2_ptctest
=
0
;
static
int
__init
ptc_test
(
char
*
str
)
{
get_option
(
&
str
,
&
sn2_ptctest
);
return
1
;
}
__setup
(
"ptctest="
,
ptc_test
);
static
inline
int
ptc_lock
(
unsigned
long
*
flagp
)
{
unsigned
long
opt
=
sn2_ptctest
&
255
;
switch
(
opt
)
{
case
0x00
:
spin_lock_irqsave
(
&
sn2_global_ptc_lock
,
*
flagp
);
break
;
case
0x01
:
spin_lock_irqsave
(
&
sn_nodepda
->
ptc_lock
,
*
flagp
);
break
;
case
0x02
:
local_irq_save
(
*
flagp
);
break
;
case
0x10
:
spin_lock
(
&
sn2_global_ptc_lock
);
break
;
case
0x11
:
spin_lock
(
&
sn_nodepda
->
ptc_lock
);
break
;
case
0x12
:
break
;
default:
BUG
();
}
return
opt
;
}
static
inline
void
ptc_unlock
(
unsigned
long
flags
,
int
opt
)
{
switch
(
opt
)
{
case
0x00
:
spin_unlock_irqrestore
(
&
sn2_global_ptc_lock
,
flags
);
break
;
case
0x01
:
spin_unlock_irqrestore
(
&
sn_nodepda
->
ptc_lock
,
flags
);
break
;
case
0x02
:
local_irq_restore
(
flags
);
break
;
case
0x10
:
spin_unlock
(
&
sn2_global_ptc_lock
);
break
;
case
0x11
:
spin_unlock
(
&
sn_nodepda
->
ptc_lock
);
break
;
case
0x12
:
break
;
default:
BUG
();
}
}
#else
#define sn2_ptctest 0
#define local_node_uses_ptc_ga(sh1) ((sh1) ? 1 : 0)
#define max_active_pio(sh1) ((sh1) ? 32 : 7)
#define reset_max_active_on_deadlock() 1
#define PTC_LOCK(sh1) ((sh1) ? &sn2_global_ptc_lock : &sn_nodepda->ptc_lock)
static
inline
int
ptc_lock
(
unsigned
long
*
flagp
)
static
inline
void
ptc_lock
(
int
sh1
,
unsigned
long
*
flagp
)
{
spin_lock_irqsave
(
&
sn2_global_ptc_lock
,
*
flagp
);
return
0
;
spin_lock_irqsave
(
PTC_LOCK
(
sh1
),
*
flagp
);
}
static
inline
void
ptc_unlock
(
unsigned
long
flags
,
int
opt
)
static
inline
void
ptc_unlock
(
int
sh1
,
unsigned
long
flags
)
{
spin_unlock_irqrestore
(
&
sn2_global_ptc_lock
,
flags
);
spin_unlock_irqrestore
(
PTC_LOCK
(
sh1
)
,
flags
);
}
#endif
struct
ptc_stats
{
unsigned
long
ptc_l
;
...
...
@@ -151,27 +75,30 @@ struct ptc_stats {
unsigned
long
shub_ptc_flushes
;
unsigned
long
nodes_flushed
;
unsigned
long
deadlocks
;
unsigned
long
deadlocks2
;
unsigned
long
lock_itc_clocks
;
unsigned
long
shub_itc_clocks
;
unsigned
long
shub_itc_clocks_max
;
unsigned
long
shub_ptc_flushes_not_my_mm
;
};
static
inline
unsigned
long
wait_piowc
(
void
)
{
volatile
unsigned
long
*
piows
,
zeroval
;
unsigned
long
ws
;
volatile
unsigned
long
*
piows
;
unsigned
long
zeroval
,
ws
;
piows
=
pda
->
pio_write_status_addr
;
zeroval
=
pda
->
pio_write_status_val
;
do
{
cpu_relax
();
}
while
(((
ws
=
*
piows
)
&
SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK
)
!=
zeroval
);
return
ws
;
return
(
ws
&
SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK
)
!=
0
;
}
void
sn_tlb_migrate_finish
(
struct
mm_struct
*
mm
)
{
if
(
mm
==
current
->
mm
)
/* flush_tlb_mm is inefficient if more than 1 users of mm */
if
(
mm
==
current
->
mm
&&
mm
&&
atomic_read
(
&
mm
->
mm_users
)
==
1
)
flush_tlb_mm
(
mm
);
}
...
...
@@ -201,12 +128,14 @@ void
sn2_global_tlb_purge
(
struct
mm_struct
*
mm
,
unsigned
long
start
,
unsigned
long
end
,
unsigned
long
nbits
)
{
int
i
,
opt
,
shub1
,
cnode
,
mynasid
,
cpu
,
lcpu
=
0
,
nasid
,
flushed
=
0
;
int
mymm
=
(
mm
==
current
->
active_mm
&&
current
->
mm
);
int
i
,
ibegin
,
shub1
,
cnode
,
mynasid
,
cpu
,
lcpu
=
0
,
nasid
;
int
mymm
=
(
mm
==
current
->
active_mm
&&
mm
==
current
->
mm
);
int
use_cpu_ptcga
;
volatile
unsigned
long
*
ptc0
,
*
ptc1
;
unsigned
long
itc
,
itc2
,
flags
,
data0
=
0
,
data1
=
0
,
rr_value
;
unsigned
long
itc
,
itc2
,
flags
,
data0
=
0
,
data1
=
0
,
rr_value
,
old_rr
=
0
;
short
nasids
[
MAX_NUMNODES
],
nix
;
nodemask_t
nodes_flushed
;
int
active
,
max_active
,
deadlock
;
nodes_clear
(
nodes_flushed
);
i
=
0
;
...
...
@@ -267,41 +196,56 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
mynasid
=
get_nasid
();
use_cpu_ptcga
=
local_node_uses_ptc_ga
(
shub1
);
max_active
=
max_active_pio
(
shub1
);
itc
=
ia64_get_itc
();
opt
=
ptc_lock
(
&
flags
);
ptc_lock
(
shub1
,
&
flags
);
itc2
=
ia64_get_itc
();
__get_cpu_var
(
ptcstats
).
lock_itc_clocks
+=
itc2
-
itc
;
__get_cpu_var
(
ptcstats
).
shub_ptc_flushes
++
;
__get_cpu_var
(
ptcstats
).
nodes_flushed
+=
nix
;
if
(
!
mymm
)
__get_cpu_var
(
ptcstats
).
shub_ptc_flushes_not_my_mm
++
;
if
(
use_cpu_ptcga
&&
!
mymm
)
{
old_rr
=
ia64_get_rr
(
start
);
ia64_set_rr
(
start
,
(
old_rr
&
0xff
)
|
(
rr_value
<<
8
));
ia64_srlz_d
();
}
wait_piowc
();
do
{
if
(
shub1
)
data1
=
start
|
(
1UL
<<
SH1_PTC_1_START_SHFT
);
else
data0
=
(
data0
&
~
SH2_PTC_ADDR_MASK
)
|
(
start
&
SH2_PTC_ADDR_MASK
);
for
(
i
=
0
;
i
<
nix
;
i
++
)
{
deadlock
=
0
;
active
=
0
;
for
(
ibegin
=
0
,
i
=
0
;
i
<
nix
;
i
++
)
{
nasid
=
nasids
[
i
];
if
(
(
!
(
sn2_ptctest
&
3
))
&&
unlikely
(
nasid
==
mynasid
&&
mymm
))
{
if
(
use_cpu_ptcga
&&
unlikely
(
nasid
==
mynasid
))
{
ia64_ptcga
(
start
,
nbits
<<
2
);
ia64_srlz_i
();
}
else
{
ptc0
=
CHANGE_NASID
(
nasid
,
ptc0
);
if
(
ptc1
)
ptc1
=
CHANGE_NASID
(
nasid
,
ptc1
);
pio_atomic_phys_write_mmrs
(
ptc0
,
data0
,
ptc1
,
data1
);
flushed
=
1
;
pio_atomic_phys_write_mmrs
(
ptc0
,
data0
,
ptc1
,
data1
);
active
++
;
}
if
(
active
>=
max_active
||
i
==
(
nix
-
1
))
{
if
((
deadlock
=
wait_piowc
()))
{
sn2_ptc_deadlock_recovery
(
nasids
,
ibegin
,
i
,
mynasid
,
ptc0
,
data0
,
ptc1
,
data1
);
if
(
reset_max_active_on_deadlock
())
max_active
=
1
;
}
active
=
0
;
ibegin
=
i
+
1
;
}
if
(
flushed
&&
(
wait_piowc
()
&
(
SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK
)))
{
sn2_ptc_deadlock_recovery
(
nasids
,
nix
,
mynasid
,
ptc0
,
data0
,
ptc1
,
data1
);
}
start
+=
(
1UL
<<
nbits
);
}
while
(
start
<
end
);
itc2
=
ia64_get_itc
()
-
itc2
;
...
...
@@ -309,7 +253,12 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
if
(
itc2
>
__get_cpu_var
(
ptcstats
).
shub_itc_clocks_max
)
__get_cpu_var
(
ptcstats
).
shub_itc_clocks_max
=
itc2
;
ptc_unlock
(
flags
,
opt
);
if
(
old_rr
)
{
ia64_set_rr
(
start
,
old_rr
);
ia64_srlz_d
();
}
ptc_unlock
(
shub1
,
flags
);
preempt_enable
();
}
...
...
@@ -321,27 +270,30 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
* TLB flush transaction. The recovery sequence is somewhat tricky & is
* coded in assembly language.
*/
void
sn2_ptc_deadlock_recovery
(
short
*
nasids
,
short
nix
,
int
mynasid
,
volatile
unsigned
long
*
ptc0
,
unsigned
long
data0
,
void
sn2_ptc_deadlock_recovery
(
short
*
nasids
,
short
ib
,
short
ie
,
int
mynasid
,
volatile
unsigned
long
*
ptc0
,
unsigned
long
data0
,
volatile
unsigned
long
*
ptc1
,
unsigned
long
data1
)
{
extern
void
sn2_ptc_deadlock_recovery_core
(
volatile
unsigned
long
*
,
unsigned
long
,
extern
unsigned
long
sn2_ptc_deadlock_recovery_core
(
volatile
unsigned
long
*
,
unsigned
long
,
volatile
unsigned
long
*
,
unsigned
long
,
volatile
unsigned
long
*
,
unsigned
long
);
short
nasid
,
i
;
unsigned
long
*
piows
,
zeroval
;
unsigned
long
*
piows
,
zeroval
,
n
;
__get_cpu_var
(
ptcstats
).
deadlocks
++
;
piows
=
(
unsigned
long
*
)
pda
->
pio_write_status_addr
;
zeroval
=
pda
->
pio_write_status_val
;
for
(
i
=
0
;
i
<
nix
;
i
++
)
{
for
(
i
=
ib
;
i
<=
ie
;
i
++
)
{
nasid
=
nasids
[
i
];
if
(
!
(
sn2_ptctest
&
3
)
&&
nasid
==
mynasid
)
if
(
local_node_uses_ptc_ga
(
is_shub1
()
)
&&
nasid
==
mynasid
)
continue
;
ptc0
=
CHANGE_NASID
(
nasid
,
ptc0
);
if
(
ptc1
)
ptc1
=
CHANGE_NASID
(
nasid
,
ptc1
);
sn2_ptc_deadlock_recovery_core
(
ptc0
,
data0
,
ptc1
,
data1
,
piows
,
zeroval
);
n
=
sn2_ptc_deadlock_recovery_core
(
ptc0
,
data0
,
ptc1
,
data1
,
piows
,
zeroval
);
__get_cpu_var
(
ptcstats
).
deadlocks2
+=
n
;
}
}
...
...
@@ -452,20 +404,22 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data)
cpu
=
*
(
loff_t
*
)
data
;
if
(
!
cpu
)
{
seq_printf
(
file
,
"# ptc_l change_rid shub_ptc_flushes shub_nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max
\n
"
);
seq_printf
(
file
,
"# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2
\n
"
);
seq_printf
(
file
,
"# ptctest %d
\n
"
,
sn2_ptctest
);
}
if
(
cpu
<
NR_CPUS
&&
cpu_online
(
cpu
))
{
stat
=
&
per_cpu
(
ptcstats
,
cpu
);
seq_printf
(
file
,
"cpu %d %ld %ld %ld %ld %ld %ld %ld %ld
\n
"
,
cpu
,
stat
->
ptc_l
,
seq_printf
(
file
,
"cpu %d %ld %ld %ld %ld %ld %ld %ld %ld
%ld %ld
\n
"
,
cpu
,
stat
->
ptc_l
,
stat
->
change_rid
,
stat
->
shub_ptc_flushes
,
stat
->
nodes_flushed
,
stat
->
deadlocks
,
1000
*
stat
->
lock_itc_clocks
/
per_cpu
(
cpu_info
,
cpu
).
cyc_per_usec
,
1000
*
stat
->
shub_itc_clocks
/
per_cpu
(
cpu_info
,
cpu
).
cyc_per_usec
,
1000
*
stat
->
shub_itc_clocks_max
/
per_cpu
(
cpu_info
,
cpu
).
cyc_per_usec
);
1000
*
stat
->
shub_itc_clocks_max
/
per_cpu
(
cpu_info
,
cpu
).
cyc_per_usec
,
stat
->
shub_ptc_flushes_not_my_mm
,
stat
->
deadlocks2
);
}
return
0
;
}
...
...
@@ -476,7 +430,7 @@ static struct seq_operations sn2_ptc_seq_ops = {
.
show
=
sn2_ptc_seq_show
};
int
sn2_ptc_proc_open
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
sn2_ptc_proc_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
sn2_ptc_seq_ops
);
}
...
...
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