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
Kirill Smelkov
linux
Commits
8e517818
Commit
8e517818
authored
Jan 12, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://ppc.bkbits.net/for-linus-ppc64
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
a1940218
980e2c9b
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
323 additions
and
300 deletions
+323
-300
arch/ppc/lib/string.S
arch/ppc/lib/string.S
+25
-14
arch/ppc/platforms/k2_pci.c
arch/ppc/platforms/k2_pci.c
+7
-0
arch/ppc/syslib/cpc710.h
arch/ppc/syslib/cpc710.h
+6
-0
arch/ppc/syslib/mpc10x_common.c
arch/ppc/syslib/mpc10x_common.c
+24
-0
arch/ppc/syslib/todc_time.c
arch/ppc/syslib/todc_time.c
+4
-0
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/sys_sparc32.c
+0
-55
arch/sparc64/kernel/systbls.S
arch/sparc64/kernel/systbls.S
+2
-2
drivers/serial/sunzilog.c
drivers/serial/sunzilog.c
+89
-65
fs/compat.c
fs/compat.c
+1
-0
include/asm-ppc/mpc10x.h
include/asm-ppc/mpc10x.h
+1
-0
include/asm-ppc/tlb.h
include/asm-ppc/tlb.h
+2
-6
include/asm-sparc64/compat.h
include/asm-sparc64/compat.h
+13
-0
include/asm-sparc64/statfs.h
include/asm-sparc64/statfs.h
+0
-14
net/bridge/netfilter/ebtables.c
net/bridge/netfilter/ebtables.c
+145
-143
net/ipv4/route.c
net/ipv4/route.c
+2
-0
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_ipv4.c
+2
-1
No files found.
arch/ppc/lib/string.S
View file @
8e517818
...
@@ -507,18 +507,18 @@ _GLOBAL(__copy_tofrom_user)
...
@@ -507,18 +507,18 @@ _GLOBAL(__copy_tofrom_user)
blr
blr
/*
read
fault
,
initial
single
-
byte
copy
*/
/*
read
fault
,
initial
single
-
byte
copy
*/
100
:
li
r
4
,
0
100
:
li
r
9
,
0
b
90
f
b
90
f
/*
write
fault
,
initial
single
-
byte
copy
*/
/*
write
fault
,
initial
single
-
byte
copy
*/
101
:
li
r
4
,
1
101
:
li
r
9
,
1
90
:
subf
r5
,
r8
,
r5
90
:
subf
r5
,
r8
,
r5
li
r3
,
0
li
r3
,
0
b
99
f
b
99
f
/*
read
fault
,
initial
word
copy
*/
/*
read
fault
,
initial
word
copy
*/
102
:
li
r
4
,
0
102
:
li
r
9
,
0
b
91
f
b
91
f
/*
write
fault
,
initial
word
copy
*/
/*
write
fault
,
initial
word
copy
*/
103
:
li
r
4
,
1
103
:
li
r
9
,
1
91
:
li
r3
,
2
91
:
li
r3
,
2
b
99
f
b
99
f
...
@@ -542,38 +542,47 @@ _GLOBAL(__copy_tofrom_user)
...
@@ -542,38 +542,47 @@ _GLOBAL(__copy_tofrom_user)
#endif
#endif
/*
read
fault
in
cacheline
loop
*/
/*
read
fault
in
cacheline
loop
*/
104
:
li
r
4
,
0
104
:
li
r
9
,
0
b
92
f
b
92
f
/*
fault
on
dcbz
(
effectively
a
write
fault
)
*/
/*
fault
on
dcbz
(
effectively
a
write
fault
)
*/
/*
or
write
fault
in
cacheline
loop
*/
/*
or
write
fault
in
cacheline
loop
*/
105
:
li
r
4
,
1
105
:
li
r
9
,
1
92
:
li
r3
,
LG_CACHELINE_BYTES
92
:
li
r3
,
LG_CACHELINE_BYTES
b
99
f
b
99
f
/*
read
fault
in
final
word
loop
*/
/*
read
fault
in
final
word
loop
*/
108
:
li
r
4
,
0
108
:
li
r
9
,
0
b
93
f
b
93
f
/*
write
fault
in
final
word
loop
*/
/*
write
fault
in
final
word
loop
*/
109
:
li
r
4
,
1
109
:
li
r
9
,
1
93
:
andi
.
r5
,
r5
,
3
93
:
andi
.
r5
,
r5
,
3
li
r3
,
2
li
r3
,
2
b
99
f
b
99
f
/*
read
fault
in
final
byte
loop
*/
/*
read
fault
in
final
byte
loop
*/
110
:
li
r
4
,
0
110
:
li
r
9
,
0
b
94
f
b
94
f
/*
write
fault
in
final
byte
loop
*/
/*
write
fault
in
final
byte
loop
*/
111
:
li
r
4
,
1
111
:
li
r
9
,
1
94
:
li
r5
,
0
94
:
li
r5
,
0
li
r3
,
0
li
r3
,
0
/*
/*
*
At
this
stage
the
number
of
bytes
not
copied
is
*
At
this
stage
the
number
of
bytes
not
copied
is
*
r5
+
(
ctr
<<
r3
),
and
r
4
is
0
for
read
or
1
for
write
.
*
r5
+
(
ctr
<<
r3
),
and
r
9
is
0
for
read
or
1
for
write
.
*/
*/
99
:
mfctr
r0
99
:
mfctr
r0
slw
r3
,
r0
,
r3
slw
r3
,
r0
,
r3
add
r3
,
r3
,
r5
add
.
r3
,
r3
,
r5
cmpwi
0
,
r4
,
0
beq
120
f
/*
shouldn
't happen */
cmpwi
0
,
r9
,
0
bne
120
f
bne
120
f
/*
for
read
fault
,
clear
out
the
destination
:
r3
bytes
starting
at
4
(
r6
)
*/
/*
for
a
read
fault
,
first
try
to
continue
the
copy
one
byte
at
a
time
*/
mtctr
r3
130
:
lbz
r0
,
4
(
r4
)
131
:
stb
r0
,
4
(
r6
)
addi
r4
,
r4
,
1
addi
r6
,
r6
,
1
bdnz
130
b
/*
then
clear
out
the
destination
:
r3
bytes
starting
at
4
(
r6
)
*/
132
:
mfctr
r3
srwi
.
r0
,
r3
,
2
srwi
.
r0
,
r3
,
2
li
r9
,
0
li
r9
,
0
mtctr
r0
mtctr
r0
...
@@ -594,6 +603,8 @@ _GLOBAL(__copy_tofrom_user)
...
@@ -594,6 +603,8 @@ _GLOBAL(__copy_tofrom_user)
.
long
31
b
,
109
b
.
long
31
b
,
109
b
.
long
40
b
,
110
b
.
long
40
b
,
110
b
.
long
41
b
,
111
b
.
long
41
b
,
111
b
.
long
130
b
,
132
b
.
long
131
b
,
120
b
.
long
112
b
,
120
b
.
long
112
b
,
120
b
.
long
114
b
,
120
b
.
long
114
b
,
120
b
.
text
.
text
...
...
arch/ppc/platforms/k2_pci.c
View file @
8e517818
...
@@ -156,6 +156,13 @@ void k2_setup_hoses(void)
...
@@ -156,6 +156,13 @@ void k2_setup_hoses(void)
__raw_writel
(
0x00000080
,
K2_PCI32_BAR
+
PSBAR
);
/* Base@0x80 */
__raw_writel
(
0x00000080
,
K2_PCI32_BAR
+
PSBAR
);
/* Base@0x80 */
__raw_writel
(
0x00000000
,
K2_PCI32_BAR
+
PPBAR
);
__raw_writel
(
0x00000000
,
K2_PCI32_BAR
+
PPBAR
);
__raw_writel
(
0xc0000000
,
K2_PCI32_BAR
+
BPMDLK
);
__raw_writel
(
0xd0000000
,
K2_PCI32_BAR
+
TPMDLK
);
__raw_writel
(
0x80000000
,
K2_PCI32_BAR
+
BIODLK
);
__raw_writel
(
0x80100000
,
K2_PCI32_BAR
+
TIODLK
);
__raw_writel
(
0xe0008000
,
K2_PCI32_BAR
+
DLKCTRL
);
__raw_writel
(
0xffffffff
,
K2_PCI32_BAR
+
DLKDEV
);
/* PCI64 mappings */
/* PCI64 mappings */
__raw_writel
(
0x00100000
,
K2_PCI64_BAR
+
PIBAR
);
/* PCI I/O base */
__raw_writel
(
0x00100000
,
K2_PCI64_BAR
+
PIBAR
);
/* PCI I/O base */
__raw_writel
(
0x10000000
,
K2_PCI64_BAR
+
PMBAR
);
/* PCI Mem base */
__raw_writel
(
0x10000000
,
K2_PCI64_BAR
+
PMBAR
);
/* PCI Mem base */
...
...
arch/ppc/syslib/cpc710.h
View file @
8e517818
...
@@ -61,6 +61,12 @@
...
@@ -61,6 +61,12 @@
#define BARPP 0x000f8130
#define BARPP 0x000f8130
#define PSBAR 0x000f8140
#define PSBAR 0x000f8140
#define PPBAR 0x000f8150
#define PPBAR 0x000f8150
#define BPMDLK 0x000f8200
/* Bottom of Peripheral Memory Space */
#define TPMDLK 0x000f8210
/* Top of Peripheral Memory Space */
#define BIODLK 0x000f8220
/* Bottom of Peripheral I/O Space */
#define TIODLK 0x000f8230
/* Top of Perioheral I/O Space */
#define DLKCTRL 0x000f8240
/* Deadlock control */
#define DLKDEV 0x000f8250
/* Deadlock device */
/* System standard configuration registers space */
/* System standard configuration registers space */
#define DCR 0xff200000
#define DCR 0xff200000
...
...
arch/ppc/syslib/mpc10x_common.c
View file @
8e517818
...
@@ -243,6 +243,8 @@ mpc10x_bridge_init(struct pci_controller *hose,
...
@@ -243,6 +243,8 @@ mpc10x_bridge_init(struct pci_controller *hose,
#ifdef CONFIG_MPC10X_STORE_GATHERING
#ifdef CONFIG_MPC10X_STORE_GATHERING
mpc10x_enable_store_gathering
(
hose
);
mpc10x_enable_store_gathering
(
hose
);
#else
mpc10x_disable_store_gathering
(
hose
);
#endif
#endif
if
(
ppc_md
.
progress
)
ppc_md
.
progress
(
"mpc10x:exit"
,
0x100
);
if
(
ppc_md
.
progress
)
ppc_md
.
progress
(
"mpc10x:exit"
,
0x100
);
...
@@ -376,3 +378,25 @@ mpc10x_enable_store_gathering(struct pci_controller *hose)
...
@@ -376,3 +378,25 @@ mpc10x_enable_store_gathering(struct pci_controller *hose)
return
0
;
return
0
;
}
}
int
__init
mpc10x_disable_store_gathering
(
struct
pci_controller
*
hose
)
{
uint
picr1
;
early_read_config_dword
(
hose
,
0
,
PCI_DEVFN
(
0
,
0
),
MPC10X_CFG_PICR1_REG
,
&
picr1
);
picr1
&=
~
MPC10X_CFG_PICR1_ST_GATH_EN
;
early_write_config_dword
(
hose
,
0
,
PCI_DEVFN
(
0
,
0
),
MPC10X_CFG_PICR1_REG
,
picr1
);
return
0
;
}
arch/ppc/syslib/todc_time.c
View file @
8e517818
...
@@ -240,6 +240,7 @@ todc_get_rtc_time(void)
...
@@ -240,6 +240,7 @@ todc_get_rtc_time(void)
switch
(
todc_info
->
rtc_type
)
{
switch
(
todc_info
->
rtc_type
)
{
case
TODC_TYPE_DS1557
:
case
TODC_TYPE_DS1557
:
case
TODC_TYPE_DS1743
:
case
TODC_TYPE_DS1746
:
/* XXXX BAD HACK -> FIX */
case
TODC_TYPE_DS1746
:
/* XXXX BAD HACK -> FIX */
case
TODC_TYPE_DS1747
:
case
TODC_TYPE_DS1747
:
break
;
break
;
...
@@ -274,6 +275,7 @@ todc_get_rtc_time(void)
...
@@ -274,6 +275,7 @@ todc_get_rtc_time(void)
if
(
todc_info
->
rtc_type
!=
TODC_TYPE_MC146818
)
{
if
(
todc_info
->
rtc_type
!=
TODC_TYPE_MC146818
)
{
switch
(
todc_info
->
rtc_type
)
{
switch
(
todc_info
->
rtc_type
)
{
case
TODC_TYPE_DS1557
:
case
TODC_TYPE_DS1557
:
case
TODC_TYPE_DS1743
:
case
TODC_TYPE_DS1746
:
/* XXXX BAD HACK -> FIX */
case
TODC_TYPE_DS1746
:
/* XXXX BAD HACK -> FIX */
case
TODC_TYPE_DS1747
:
case
TODC_TYPE_DS1747
:
break
;
break
;
...
@@ -367,6 +369,7 @@ static unsigned char __init todc_read_timereg(int addr)
...
@@ -367,6 +369,7 @@ static unsigned char __init todc_read_timereg(int addr)
switch
(
todc_info
->
rtc_type
)
{
switch
(
todc_info
->
rtc_type
)
{
case
TODC_TYPE_DS1557
:
case
TODC_TYPE_DS1557
:
case
TODC_TYPE_DS1743
:
case
TODC_TYPE_DS1746
:
/* XXXX BAD HACK -> FIX */
case
TODC_TYPE_DS1746
:
/* XXXX BAD HACK -> FIX */
case
TODC_TYPE_DS1747
:
case
TODC_TYPE_DS1747
:
case
TODC_TYPE_MC146818
:
case
TODC_TYPE_MC146818
:
...
@@ -381,6 +384,7 @@ static unsigned char __init todc_read_timereg(int addr)
...
@@ -381,6 +384,7 @@ static unsigned char __init todc_read_timereg(int addr)
switch
(
todc_info
->
rtc_type
)
{
switch
(
todc_info
->
rtc_type
)
{
case
TODC_TYPE_DS1557
:
case
TODC_TYPE_DS1557
:
case
TODC_TYPE_DS1743
:
case
TODC_TYPE_DS1746
:
/* XXXX BAD HACK -> FIX */
case
TODC_TYPE_DS1746
:
/* XXXX BAD HACK -> FIX */
case
TODC_TYPE_DS1747
:
case
TODC_TYPE_DS1747
:
case
TODC_TYPE_MC146818
:
case
TODC_TYPE_MC146818
:
...
...
arch/sparc64/kernel/sys_sparc32.c
View file @
8e517818
...
@@ -840,61 +840,6 @@ asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long a
...
@@ -840,61 +840,6 @@ asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long a
return
sys32_fcntl
(
fd
,
cmd
,
arg
);
return
sys32_fcntl
(
fd
,
cmd
,
arg
);
}
}
static
int
put_statfs
(
struct
statfs32
*
ubuf
,
struct
statfs
*
kbuf
)
{
int
err
;
err
=
put_user
(
kbuf
->
f_type
,
&
ubuf
->
f_type
);
err
|=
__put_user
(
kbuf
->
f_bsize
,
&
ubuf
->
f_bsize
);
err
|=
__put_user
(
kbuf
->
f_blocks
,
&
ubuf
->
f_blocks
);
err
|=
__put_user
(
kbuf
->
f_bfree
,
&
ubuf
->
f_bfree
);
err
|=
__put_user
(
kbuf
->
f_bavail
,
&
ubuf
->
f_bavail
);
err
|=
__put_user
(
kbuf
->
f_files
,
&
ubuf
->
f_files
);
err
|=
__put_user
(
kbuf
->
f_ffree
,
&
ubuf
->
f_ffree
);
err
|=
__put_user
(
kbuf
->
f_namelen
,
&
ubuf
->
f_namelen
);
err
|=
__put_user
(
kbuf
->
f_fsid
.
val
[
0
],
&
ubuf
->
f_fsid
.
val
[
0
]);
err
|=
__put_user
(
kbuf
->
f_fsid
.
val
[
1
],
&
ubuf
->
f_fsid
.
val
[
1
]);
return
err
;
}
extern
asmlinkage
int
sys_statfs
(
const
char
*
path
,
struct
statfs
*
buf
);
asmlinkage
int
sys32_statfs
(
const
char
*
path
,
struct
statfs32
*
buf
)
{
int
ret
;
struct
statfs
s
;
mm_segment_t
old_fs
=
get_fs
();
char
*
pth
;
pth
=
getname
(
path
);
ret
=
PTR_ERR
(
pth
);
if
(
!
IS_ERR
(
pth
))
{
set_fs
(
KERNEL_DS
);
ret
=
sys_statfs
((
const
char
*
)
pth
,
&
s
);
set_fs
(
old_fs
);
putname
(
pth
);
if
(
put_statfs
(
buf
,
&
s
))
return
-
EFAULT
;
}
return
ret
;
}
extern
asmlinkage
int
sys_fstatfs
(
unsigned
int
fd
,
struct
statfs
*
buf
);
asmlinkage
int
sys32_fstatfs
(
unsigned
int
fd
,
struct
statfs32
*
buf
)
{
int
ret
;
struct
statfs
s
;
mm_segment_t
old_fs
=
get_fs
();
set_fs
(
KERNEL_DS
);
ret
=
sys_fstatfs
(
fd
,
&
s
);
set_fs
(
old_fs
);
if
(
put_statfs
(
buf
,
&
s
))
return
-
EFAULT
;
return
ret
;
}
extern
asmlinkage
long
sys_truncate
(
const
char
*
path
,
unsigned
long
length
);
extern
asmlinkage
long
sys_truncate
(
const
char
*
path
,
unsigned
long
length
);
extern
asmlinkage
long
sys_ftruncate
(
unsigned
int
fd
,
unsigned
long
length
);
extern
asmlinkage
long
sys_ftruncate
(
unsigned
int
fd
,
unsigned
long
length
);
...
...
arch/sparc64/kernel/systbls.S
View file @
8e517818
...
@@ -50,7 +50,7 @@ sys_call_table32:
...
@@ -50,7 +50,7 @@ sys_call_table32:
/*
140
*/
.
word
sys32_sendfile64
,
sys_nis_syscall
,
sys_futex
,
sys_gettid
,
sys32_getrlimit
/*
140
*/
.
word
sys32_sendfile64
,
sys_nis_syscall
,
sys_futex
,
sys_gettid
,
sys32_getrlimit
.
word
sys32_setrlimit
,
sys_pivot_root
,
sys32_prctl
,
sys32_pciconfig_read
,
sys32_pciconfig_write
.
word
sys32_setrlimit
,
sys_pivot_root
,
sys32_prctl
,
sys32_pciconfig_read
,
sys32_pciconfig_write
/*
150
*/
.
word
sys_nis_syscall
,
sys_nis_syscall
,
sys_nis_syscall
,
sys_poll
,
sys_getdents64
/*
150
*/
.
word
sys_nis_syscall
,
sys_nis_syscall
,
sys_nis_syscall
,
sys_poll
,
sys_getdents64
.
word
sys32_fcntl64
,
sys_ni_syscall
,
sys32_statfs
,
sys32
_fstatfs
,
sys_oldumount
.
word
sys32_fcntl64
,
sys_ni_syscall
,
compat_sys_statfs
,
compat_sys
_fstatfs
,
sys_oldumount
/*
160
*/
.
word
sys32_sched_setaffinity
,
sys32_sched_getaffinity
,
sys_getdomainname
,
sys_setdomainname
,
sys_nis_syscall
/*
160
*/
.
word
sys32_sched_setaffinity
,
sys32_sched_getaffinity
,
sys_getdomainname
,
sys_setdomainname
,
sys_nis_syscall
.
word
sys_quotactl
,
sys_set_tid_address
,
sys32_mount
,
sys_ustat
,
sys_setxattr
.
word
sys_quotactl
,
sys_set_tid_address
,
sys32_mount
,
sys_ustat
,
sys_setxattr
/*
170
*/
.
word
sys_lsetxattr
,
sys_fsetxattr
,
sys_getxattr
,
sys_lgetxattr
,
sys32_getdents
/*
170
*/
.
word
sys_lsetxattr
,
sys_fsetxattr
,
sys_getxattr
,
sys_lgetxattr
,
sys32_getdents
...
@@ -197,7 +197,7 @@ sunos_sys_table:
...
@@ -197,7 +197,7 @@ sunos_sys_table:
.
word
sunos_nosys
,
sunos_nosys
.
word
sunos_nosys
,
sunos_nosys
/*
150
*/
.
word
sys_getsockname
,
sunos_nosys
,
sunos_nosys
/*
150
*/
.
word
sys_getsockname
,
sunos_nosys
,
sunos_nosys
.
word
sys_poll
,
sunos_nosys
,
sunos_nosys
.
word
sys_poll
,
sunos_nosys
,
sunos_nosys
.
word
sunos_getdirentries
,
sys32_statfs
,
sys32
_fstatfs
.
word
sunos_getdirentries
,
compat_sys_statfs
,
compat_sys
_fstatfs
.
word
sys_oldumount
,
sunos_nosys
,
sunos_nosys
.
word
sys_oldumount
,
sunos_nosys
,
sunos_nosys
.
word
sys_getdomainname
,
sys_setdomainname
.
word
sys_getdomainname
,
sys_setdomainname
.
word
sunos_nosys
,
sys_quotactl
,
sunos_nosys
.
word
sunos_nosys
,
sys_quotactl
,
sunos_nosys
...
...
drivers/serial/sunzilog.c
View file @
8e517818
...
@@ -112,10 +112,7 @@ struct uart_sunzilog_port {
...
@@ -112,10 +112,7 @@ struct uart_sunzilog_port {
#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel *)((PORT)->membase))
#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel *)((PORT)->membase))
#define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT))
#define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT))
#define SUNZILOG_GET_CURR_REG(PORT, REGNUM) \
(UART_ZILOG(PORT)->curregs[REGNUM])
#define SUNZILOG_SET_CURR_REG(PORT, REGNUM, REGVAL) \
((UART_ZILOG(PORT)->curregs[REGNUM]) = (REGVAL))
#define ZS_IS_KEYB(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_KEYB)
#define ZS_IS_KEYB(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_KEYB)
#define ZS_IS_MOUSE(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_MOUSE)
#define ZS_IS_MOUSE(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_MOUSE)
#define ZS_IS_CONS(UP) ((UP)->flags & SUNZILOG_FLAG_IS_CONS)
#define ZS_IS_CONS(UP) ((UP)->flags & SUNZILOG_FLAG_IS_CONS)
...
@@ -278,8 +275,7 @@ static void sunzilog_change_mouse_baud(struct uart_sunzilog_port *up)
...
@@ -278,8 +275,7 @@ static void sunzilog_change_mouse_baud(struct uart_sunzilog_port *up)
up
->
cflag
&=
~
CBAUD
;
up
->
cflag
&=
~
CBAUD
;
up
->
cflag
|=
suncore_mouse_baud_cflag_next
(
cur_cflag
,
&
new_baud
);
up
->
cflag
|=
suncore_mouse_baud_cflag_next
(
cur_cflag
,
&
new_baud
);
brg
=
BPS_TO_BRG
(
new_baud
,
brg
=
BPS_TO_BRG
(
new_baud
,
ZS_CLOCK
/
ZS_CLOCK_DIVISOR
);
(
ZS_CLOCK
/
ZS_CLOCK_DIVISOR
));
up
->
curregs
[
R12
]
=
(
brg
&
0xff
);
up
->
curregs
[
R12
]
=
(
brg
&
0xff
);
up
->
curregs
[
R13
]
=
(
brg
>>
8
)
&
0xff
;
up
->
curregs
[
R13
]
=
(
brg
>>
8
)
&
0xff
;
sunzilog_maybe_update_regs
(
up
,
ZILOG_CHANNEL_FROM_PORT
(
&
up
->
port
));
sunzilog_maybe_update_regs
(
up
,
ZILOG_CHANNEL_FROM_PORT
(
&
up
->
port
));
...
@@ -332,7 +328,7 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
...
@@ -332,7 +328,7 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
struct
zilog_channel
*
channel
,
struct
zilog_channel
*
channel
,
struct
pt_regs
*
regs
)
struct
pt_regs
*
regs
)
{
{
struct
tty_struct
*
tty
=
up
->
port
.
info
->
tty
;
struct
tty_struct
*
tty
=
up
->
port
.
info
->
tty
;
/* XXX info==NULL? */
while
(
1
)
{
while
(
1
)
{
unsigned
char
ch
,
r1
;
unsigned
char
ch
,
r1
;
...
@@ -340,7 +336,7 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
...
@@ -340,7 +336,7 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
if
(
unlikely
(
tty
->
flip
.
count
>=
TTY_FLIPBUF_SIZE
))
{
if
(
unlikely
(
tty
->
flip
.
count
>=
TTY_FLIPBUF_SIZE
))
{
tty
->
flip
.
work
.
func
((
void
*
)
tty
);
tty
->
flip
.
work
.
func
((
void
*
)
tty
);
if
(
tty
->
flip
.
count
>=
TTY_FLIPBUF_SIZE
)
if
(
tty
->
flip
.
count
>=
TTY_FLIPBUF_SIZE
)
return
;
return
;
/* XXX Ignores SysRq when we need it most. Fix. */
}
}
r1
=
read_zsreg
(
channel
,
R1
);
r1
=
read_zsreg
(
channel
,
R1
);
...
@@ -474,7 +470,7 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
...
@@ -474,7 +470,7 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
static
void
sunzilog_transmit_chars
(
struct
uart_sunzilog_port
*
up
,
static
void
sunzilog_transmit_chars
(
struct
uart_sunzilog_port
*
up
,
struct
zilog_channel
*
channel
)
struct
zilog_channel
*
channel
)
{
{
struct
circ_buf
*
xmit
=
&
up
->
port
.
info
->
xmit
;
struct
circ_buf
*
xmit
;
if
(
ZS_IS_CONS
(
up
))
{
if
(
ZS_IS_CONS
(
up
))
{
unsigned
char
status
=
sbus_readb
(
&
channel
->
control
);
unsigned
char
status
=
sbus_readb
(
&
channel
->
control
);
...
@@ -499,7 +495,12 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
...
@@ -499,7 +495,12 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
if
(
ZS_TX_STOPPED
(
up
))
{
if
(
ZS_TX_STOPPED
(
up
))
{
up
->
flags
&=
~
SUNZILOG_FLAG_TX_STOPPED
;
up
->
flags
&=
~
SUNZILOG_FLAG_TX_STOPPED
;
goto
disable_tx_int
;
sbus_writeb
(
RES_Tx_P
,
&
channel
->
control
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
return
;
}
}
if
(
up
->
port
.
x_char
)
{
if
(
up
->
port
.
x_char
)
{
...
@@ -512,8 +513,11 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
...
@@ -512,8 +513,11 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
return
;
return
;
}
}
if
(
up
->
port
.
info
==
NULL
)
goto
ack_tx_int
;
xmit
=
&
up
->
port
.
info
->
xmit
;
if
(
uart_circ_empty
(
xmit
)
||
uart_tx_stopped
(
&
up
->
port
))
if
(
uart_circ_empty
(
xmit
)
||
uart_tx_stopped
(
&
up
->
port
))
goto
disable
_tx_int
;
goto
ack
_tx_int
;
sbus_writeb
(
xmit
->
buf
[
xmit
->
tail
],
&
channel
->
data
);
sbus_writeb
(
xmit
->
buf
[
xmit
->
tail
],
&
channel
->
data
);
ZSDELAY
();
ZSDELAY
();
...
@@ -525,12 +529,15 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
...
@@ -525,12 +529,15 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
if
(
uart_circ_chars_pending
(
xmit
)
<
WAKEUP_CHARS
)
if
(
uart_circ_chars_pending
(
xmit
)
<
WAKEUP_CHARS
)
uart_write_wakeup
(
&
up
->
port
);
uart_write_wakeup
(
&
up
->
port
);
if
(
!
uart_circ_empty
(
xmit
))
if
(
uart_circ_empty
(
xmit
))
goto
ack_tx_int
;
return
;
return
;
disable_tx_int:
ack_tx_int:
up
->
curregs
[
R5
]
&=
~
TxENAB
;
sbus_writeb
(
RES_Tx_P
,
&
channel
->
control
);
write_zsreg
(
ZILOG_CHANNEL_FROM_PORT
(
&
up
->
port
),
R5
,
up
->
curregs
[
R5
]);
ZSDELAY
();
ZS_WSYNC
(
channel
);
}
}
static
void
sunzilog_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
void
sunzilog_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
...
@@ -543,7 +550,7 @@ static void sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs)
...
@@ -543,7 +550,7 @@ static void sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned
char
r3
;
unsigned
char
r3
;
spin_lock
(
&
up
->
port
.
lock
);
spin_lock
(
&
up
->
port
.
lock
);
r3
=
read_zsreg
(
channel
,
3
);
r3
=
read_zsreg
(
channel
,
R
3
);
/* Channel A */
/* Channel A */
if
(
r3
&
(
CHAEXT
|
CHATxIP
|
CHARxIP
))
{
if
(
r3
&
(
CHAEXT
|
CHATxIP
|
CHARxIP
))
{
...
@@ -679,13 +686,6 @@ static void sunzilog_start_tx(struct uart_port *port, unsigned int tty_start)
...
@@ -679,13 +686,6 @@ static void sunzilog_start_tx(struct uart_port *port, unsigned int tty_start)
up
->
flags
|=
SUNZILOG_FLAG_TX_ACTIVE
;
up
->
flags
|=
SUNZILOG_FLAG_TX_ACTIVE
;
up
->
flags
&=
~
SUNZILOG_FLAG_TX_STOPPED
;
up
->
flags
&=
~
SUNZILOG_FLAG_TX_STOPPED
;
/* Enable the transmitter. */
if
(
!
(
up
->
curregs
[
R5
]
&
TxENAB
))
{
/* NOTE: Not subject to 'transmitter active' rule. */
up
->
curregs
[
R5
]
|=
TxENAB
;
write_zsreg
(
channel
,
R5
,
up
->
curregs
[
R5
]);
}
status
=
sbus_readb
(
&
channel
->
control
);
status
=
sbus_readb
(
&
channel
->
control
);
ZSDELAY
();
ZSDELAY
();
...
@@ -785,39 +785,69 @@ static void sunzilog_break_ctl(struct uart_port *port, int break_state)
...
@@ -785,39 +785,69 @@ static void sunzilog_break_ctl(struct uart_port *port, int break_state)
spin_unlock_irqrestore
(
&
port
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
port
->
lock
,
flags
);
}
}
static
int
sunzilog_startup
(
struct
uart_port
*
port
)
static
void
__sunzilog_startup
(
struct
uart_sunzilog_port
*
up
)
{
{
struct
uart_sunzilog_port
*
up
=
UART_ZILOG
(
port
);
struct
zilog_channel
*
channel
;
struct
zilog_channel
*
channel
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
port
->
lock
,
flags
);
channel
=
ZILOG_CHANNEL_FROM_PORT
(
port
);
channel
=
ZILOG_CHANNEL_FROM_PORT
(
&
up
->
port
);
up
->
prev_status
=
sbus_readb
(
&
channel
->
control
);
up
->
prev_status
=
sbus_readb
(
&
channel
->
control
);
/* Enable receiver and transmitter. */
/* Enable receiver and transmitter. */
up
->
curregs
[
R3
]
|=
RxENAB
;
up
->
curregs
[
R3
]
|=
RxENAB
;
up
->
curregs
[
R5
]
|=
TxENAB
;
up
->
curregs
[
R5
]
|=
TxENAB
;
/* Enable RX and status interrupts. TX interrupts are enabled
up
->
curregs
[
R1
]
|=
EXT_INT_ENAB
|
INT_ALL_Rx
|
TxINT_ENAB
;
* as needed.
*/
up
->
curregs
[
R1
]
|=
EXT_INT_ENAB
|
INT_ALL_Rx
;
up
->
curregs
[
R9
]
|=
MIE
;
sunzilog_maybe_update_regs
(
up
,
channel
);
sunzilog_maybe_update_regs
(
up
,
channel
);
}
spin_unlock_irqrestore
(
&
port
->
lock
,
flags
);
static
int
sunzilog_startup
(
struct
uart_port
*
port
)
{
struct
uart_sunzilog_port
*
up
=
UART_ZILOG
(
port
);
unsigned
long
flags
;
if
(
ZS_IS_CONS
(
up
))
return
0
;
spin_lock_irqsave
(
&
port
->
lock
,
flags
);
__sunzilog_startup
(
up
);
spin_unlock_irqrestore
(
&
port
->
lock
,
flags
);
return
0
;
return
0
;
}
}
/*
* The test for ZS_IS_CONS is explained by the following e-mail:
*****
* From: Russell King <rmk@arm.linux.org.uk>
* Date: Sun, 8 Dec 2002 10:18:38 +0000
*
* On Sun, Dec 08, 2002 at 02:43:36AM -0500, Pete Zaitcev wrote:
* > I boot my 2.5 boxes using "console=ttyS0,9600" argument,
* > and I noticed that something is not right with reference
* > counting in this case. It seems that when the console
* > is open by kernel initially, this is not accounted
* > as an open, and uart_startup is not called.
*
* That is correct. We are unable to call uart_startup when the serial
* console is initialised because it may need to allocate memory (as
* request_irq does) and the memory allocators may not have been
* initialised.
*
* 1. initialise the port into a state where it can send characters in the
* console write method.
*
* 2. don't do the actual hardware shutdown in your shutdown() method (but
* do the normal software shutdown - ie, free irqs etc)
*****
*/
static
void
sunzilog_shutdown
(
struct
uart_port
*
port
)
static
void
sunzilog_shutdown
(
struct
uart_port
*
port
)
{
{
struct
uart_sunzilog_port
*
up
=
UART_ZILOG
(
port
);
struct
uart_sunzilog_port
*
up
=
UART_ZILOG
(
port
);
struct
zilog_channel
*
channel
;
struct
zilog_channel
*
channel
;
unsigned
long
flags
;
unsigned
long
flags
;
if
(
ZS_IS_CONS
(
up
))
return
;
spin_lock_irqsave
(
&
port
->
lock
,
flags
);
spin_lock_irqsave
(
&
port
->
lock
,
flags
);
channel
=
ZILOG_CHANNEL_FROM_PORT
(
port
);
channel
=
ZILOG_CHANNEL_FROM_PORT
(
port
);
...
@@ -829,7 +859,6 @@ static void sunzilog_shutdown(struct uart_port *port)
...
@@ -829,7 +859,6 @@ static void sunzilog_shutdown(struct uart_port *port)
/* Disable all interrupts and BRK assertion. */
/* Disable all interrupts and BRK assertion. */
up
->
curregs
[
R1
]
&=
~
(
EXT_INT_ENAB
|
TxINT_ENAB
|
RxINT_MASK
);
up
->
curregs
[
R1
]
&=
~
(
EXT_INT_ENAB
|
TxINT_ENAB
|
RxINT_MASK
);
up
->
curregs
[
R5
]
&=
~
SND_BRK
;
up
->
curregs
[
R5
]
&=
~
SND_BRK
;
up
->
curregs
[
R9
]
&=
~
MIE
;
sunzilog_maybe_update_regs
(
up
,
channel
);
sunzilog_maybe_update_regs
(
up
,
channel
);
spin_unlock_irqrestore
(
&
port
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
port
->
lock
,
flags
);
...
@@ -843,18 +872,15 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag,
...
@@ -843,18 +872,15 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag,
unsigned
int
iflag
,
int
brg
)
unsigned
int
iflag
,
int
brg
)
{
{
/* Don't modify MIE. */
up
->
curregs
[
R9
]
|=
NV
;
up
->
curregs
[
R10
]
=
NRZ
;
up
->
curregs
[
R10
]
=
NRZ
;
up
->
curregs
[
11
]
=
TCBR
|
RCBR
;
up
->
curregs
[
R
11
]
=
TCBR
|
RCBR
;
/* Program BAUD and clock source. */
/* Program BAUD and clock source. */
up
->
curregs
[
4
]
&=
~
XCLK_MASK
;
up
->
curregs
[
R
4
]
&=
~
XCLK_MASK
;
up
->
curregs
[
4
]
|=
X16CLK
;
up
->
curregs
[
R
4
]
|=
X16CLK
;
up
->
curregs
[
12
]
=
brg
&
0xff
;
up
->
curregs
[
R
12
]
=
brg
&
0xff
;
up
->
curregs
[
13
]
=
(
brg
>>
8
)
&
0xff
;
up
->
curregs
[
R
13
]
=
(
brg
>>
8
)
&
0xff
;
up
->
curregs
[
14
]
=
BRSRC
|
BRENAB
;
up
->
curregs
[
R
14
]
=
BRSRC
|
BRENAB
;
/* Character size, stop bits, and parity. */
/* Character size, stop bits, and parity. */
up
->
curregs
[
3
]
&=
~
RxN_MASK
;
up
->
curregs
[
3
]
&=
~
RxN_MASK
;
...
@@ -1027,7 +1053,7 @@ static void __init sunzilog_alloc_tables(void)
...
@@ -1027,7 +1053,7 @@ static void __init sunzilog_alloc_tables(void)
alloc_one_table
(
NUM_SUNZILOG
*
sizeof
(
struct
zilog_layout
*
));
alloc_one_table
(
NUM_SUNZILOG
*
sizeof
(
struct
zilog_layout
*
));
if
(
sunzilog_port_table
==
NULL
||
sunzilog_chip_regs
==
NULL
)
{
if
(
sunzilog_port_table
==
NULL
||
sunzilog_chip_regs
==
NULL
)
{
prom_printf
(
"
sunzilog_init: Cannot alloc SunZilog
tables.
\n
"
);
prom_printf
(
"
SunZilog: Cannot allocate
tables.
\n
"
);
prom_halt
();
prom_halt
();
}
}
}
}
...
@@ -1333,7 +1359,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options)
...
@@ -1333,7 +1359,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options)
unsigned
long
flags
;
unsigned
long
flags
;
int
baud
,
brg
;
int
baud
,
brg
;
printk
(
"Console: ttyS%d (
Zilog8530
)
\n
"
,
printk
(
"Console: ttyS%d (
SunZilog
)
\n
"
,
(
sunzilog_reg
.
minor
-
64
)
+
con
->
index
);
(
sunzilog_reg
.
minor
-
64
)
+
con
->
index
);
/* Get firmware console settings. */
/* Get firmware console settings. */
...
@@ -1356,21 +1382,15 @@ static int __init sunzilog_console_setup(struct console *con, char *options)
...
@@ -1356,21 +1382,15 @@ static int __init sunzilog_console_setup(struct console *con, char *options)
brg
=
BPS_TO_BRG
(
baud
,
ZS_CLOCK
/
ZS_CLOCK_DIVISOR
);
brg
=
BPS_TO_BRG
(
baud
,
ZS_CLOCK
/
ZS_CLOCK_DIVISOR
);
/*
* Temporary fix.
*/
spin_lock_init
(
&
up
->
port
.
lock
);
spin_lock_irqsave
(
&
up
->
port
.
lock
,
flags
);
spin_lock_irqsave
(
&
up
->
port
.
lock
,
flags
);
up
->
curregs
[
R15
]
=
BRKIE
;
up
->
curregs
[
R15
]
=
BRKIE
;
sunzilog_convert_to_zs
(
up
,
con
->
cflag
,
0
,
brg
);
sunzilog_convert_to_zs
(
up
,
con
->
cflag
,
0
,
brg
);
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
sunzilog_set_mctrl
(
&
up
->
port
,
TIOCM_DTR
|
TIOCM_RTS
);
sunzilog_set_mctrl
(
&
up
->
port
,
TIOCM_DTR
|
TIOCM_RTS
);
sunzilog_startup
(
&
up
->
port
);
__sunzilog_startup
(
up
);
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
return
0
;
return
0
;
}
}
...
@@ -1401,6 +1421,7 @@ static int __init sunzilog_console_init(void)
...
@@ -1401,6 +1421,7 @@ static int __init sunzilog_console_init(void)
return
0
;
return
0
;
sunzilog_console
.
index
=
i
;
sunzilog_console
.
index
=
i
;
sunzilog_port_table
[
i
].
flags
|=
SUNZILOG_FLAG_IS_CONS
;
register_console
(
&
sunzilog_console
);
register_console
(
&
sunzilog_console
);
return
0
;
return
0
;
}
}
...
@@ -1457,6 +1478,12 @@ static void __init sunzilog_prepare(void)
...
@@ -1457,6 +1478,12 @@ static void __init sunzilog_prepare(void)
struct
zilog_layout
*
rp
;
struct
zilog_layout
*
rp
;
int
channel
,
chip
;
int
channel
,
chip
;
/*
* Temporary fix.
*/
for
(
channel
=
0
;
channel
<
NUM_CHANNELS
-
1
;
channel
++
)
spin_lock_init
(
&
sunzilog_port_table
[
channel
].
port
.
lock
);
sunzilog_irq_chain
=
up
=
&
sunzilog_port_table
[
0
];
sunzilog_irq_chain
=
up
=
&
sunzilog_port_table
[
0
];
for
(
channel
=
0
;
channel
<
NUM_CHANNELS
-
1
;
channel
++
)
for
(
channel
=
0
;
channel
<
NUM_CHANNELS
-
1
;
channel
++
)
up
[
channel
].
next
=
&
up
[
channel
+
1
];
up
[
channel
].
next
=
&
up
[
channel
+
1
];
...
@@ -1504,7 +1531,7 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
...
@@ -1504,7 +1531,7 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
up
->
cflag
=
B4800
|
CS8
|
CLOCAL
|
CREAD
;
up
->
cflag
=
B4800
|
CS8
|
CLOCAL
|
CREAD
;
baud
=
4800
;
baud
=
4800
;
}
}
printk
(
KERN_INFO
"zs%d at 0x%p (irq = %s) is a
Zilog8530
\n
"
,
printk
(
KERN_INFO
"zs%d at 0x%p (irq = %s) is a
SunZilog
\n
"
,
channel
,
up
->
port
.
membase
,
__irq_itoa
(
zilog_irq
));
channel
,
up
->
port
.
membase
,
__irq_itoa
(
zilog_irq
));
up
->
curregs
[
R15
]
=
BRKIE
;
up
->
curregs
[
R15
]
=
BRKIE
;
...
@@ -1534,10 +1561,8 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
...
@@ -1534,10 +1561,8 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
serio_register_port
(
&
up
->
serio
);
serio_register_port
(
&
up
->
serio
);
#endif
#endif
spin_unlock
(
&
up
->
port
.
lock
);
sunzilog_set_mctrl
(
&
up
->
port
,
TIOCM_DTR
|
TIOCM_RTS
);
sunzilog_set_mctrl
(
&
up
->
port
,
TIOCM_DTR
|
TIOCM_RTS
);
sunzilog_startup
(
&
up
->
port
);
__sunzilog_startup
(
up
);
spin_lock
(
&
up
->
port
.
lock
);
}
}
static
void
__init
sunzilog_init_hw
(
void
)
static
void
__init
sunzilog_init_hw
(
void
)
...
@@ -1560,8 +1585,6 @@ static void __init sunzilog_init_hw(void)
...
@@ -1560,8 +1585,6 @@ static void __init sunzilog_init_hw(void)
if
(
i
==
KEYBOARD_LINE
||
i
==
MOUSE_LINE
)
{
if
(
i
==
KEYBOARD_LINE
||
i
==
MOUSE_LINE
)
{
sunzilog_init_kbdms
(
up
,
i
);
sunzilog_init_kbdms
(
up
,
i
);
}
else
if
(
ZS_IS_CONS
(
up
))
{
/* sunzilog_console_setup takes care of this */
}
else
{
}
else
{
/* Normal serial TTY. */
/* Normal serial TTY. */
up
->
parity_mask
=
0xff
;
up
->
parity_mask
=
0xff
;
...
@@ -1572,11 +1595,12 @@ static void __init sunzilog_init_hw(void)
...
@@ -1572,11 +1595,12 @@ static void __init sunzilog_init_hw(void)
up
->
curregs
[
R10
]
=
NRZ
;
up
->
curregs
[
R10
]
=
NRZ
;
up
->
curregs
[
R11
]
=
TCBR
|
RCBR
;
up
->
curregs
[
R11
]
=
TCBR
|
RCBR
;
baud
=
9600
;
baud
=
9600
;
brg
=
BPS_TO_BRG
(
baud
,
(
ZS_CLOCK
/
ZS_CLOCK_DIVISOR
)
);
brg
=
BPS_TO_BRG
(
baud
,
ZS_CLOCK
/
ZS_CLOCK_DIVISOR
);
up
->
curregs
[
R12
]
=
(
brg
&
0xff
);
up
->
curregs
[
R12
]
=
(
brg
&
0xff
);
up
->
curregs
[
R13
]
=
(
brg
>>
8
)
&
0xff
;
up
->
curregs
[
R13
]
=
(
brg
>>
8
)
&
0xff
;
up
->
curregs
[
R14
]
=
BRSRC
|
BRENAB
;
up
->
curregs
[
R14
]
=
BRSRC
|
BRENAB
;
sunzilog_maybe_update_regs
(
up
,
channel
);
__load_zsregs
(
channel
,
up
->
curregs
);
write_zsreg
(
channel
,
R9
,
up
->
curregs
[
R9
]);
}
}
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
...
...
fs/compat.c
View file @
8e517818
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
#include <linux/fcntl.h>
#include <linux/fcntl.h>
#include <linux/namei.h>
#include <linux/namei.h>
#include <linux/file.h>
#include <linux/file.h>
#include <linux/vfs.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
...
...
include/asm-ppc/mpc10x.h
View file @
8e517818
...
@@ -164,5 +164,6 @@ int mpc10x_bridge_init(struct pci_controller *hose,
...
@@ -164,5 +164,6 @@ int mpc10x_bridge_init(struct pci_controller *hose,
uint
phys_eumb_base
);
uint
phys_eumb_base
);
unsigned
long
mpc10x_get_mem_size
(
uint
mem_map
);
unsigned
long
mpc10x_get_mem_size
(
uint
mem_map
);
int
mpc10x_enable_store_gathering
(
struct
pci_controller
*
hose
);
int
mpc10x_enable_store_gathering
(
struct
pci_controller
*
hose
);
int
mpc10x_disable_store_gathering
(
struct
pci_controller
*
hose
);
#endif
/* __PPC_KERNEL_MPC10X_H */
#endif
/* __PPC_KERNEL_MPC10X_H */
include/asm-ppc/tlb.h
View file @
8e517818
...
@@ -21,8 +21,8 @@
...
@@ -21,8 +21,8 @@
#ifdef CONFIG_PPC_STD_MMU
#ifdef CONFIG_PPC_STD_MMU
/* Classic PPC with hash-table based MMU... */
/* Classic PPC with hash-table based MMU... */
struct
free_pte_ctx
;
struct
mmu_gather
;
extern
void
tlb_flush
(
struct
free_pte_ctx
*
tlb
);
extern
void
tlb_flush
(
struct
mmu_gather
*
tlb
);
/* Get the generic bits... */
/* Get the generic bits... */
#include <asm-generic/tlb.h>
#include <asm-generic/tlb.h>
...
@@ -44,10 +44,6 @@ static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
...
@@ -44,10 +44,6 @@ static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
#else
#else
/* Embedded PPC with software-loaded TLB, very simple... */
/* Embedded PPC with software-loaded TLB, very simple... */
struct
flush_tlb_arch
{
};
#define tlb_init_arch(tlb, full_flush) do { } while (0)
#define tlb_finish_arch(tlb) do { } while (0)
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
...
...
include/asm-sparc64/compat.h
View file @
8e517818
...
@@ -64,4 +64,17 @@ struct compat_flock {
...
@@ -64,4 +64,17 @@ struct compat_flock {
short
__unused
;
short
__unused
;
};
};
struct
compat_statfs
{
int
f_type
;
int
f_bsize
;
int
f_blocks
;
int
f_bfree
;
int
f_bavail
;
int
f_files
;
int
f_ffree
;
compat_fsid_t
f_fsid
;
int
f_namelen
;
/* SunOS ignores this field. */
int
f_spare
[
6
];
};
#endif
/* _ASM_SPARC64_COMPAT_H */
#endif
/* _ASM_SPARC64_COMPAT_H */
include/asm-sparc64/statfs.h
View file @
8e517818
...
@@ -5,25 +5,11 @@
...
@@ -5,25 +5,11 @@
#ifndef __KERNEL_STRICT_NAMES
#ifndef __KERNEL_STRICT_NAMES
#include <linux/types.h>
#include <linux/types.h>
#include <linux/compat.h>
/* for compat_fsid_t */
typedef
__kernel_fsid_t
fsid_t
;
typedef
__kernel_fsid_t
fsid_t
;
#endif
#endif
struct
statfs32
{
int
f_type
;
int
f_bsize
;
int
f_blocks
;
int
f_bfree
;
int
f_bavail
;
int
f_files
;
int
f_ffree
;
compat_fsid_t
f_fsid
;
int
f_namelen
;
/* SunOS ignores this field. */
int
f_spare
[
6
];
};
struct
statfs
{
struct
statfs
{
long
f_type
;
long
f_type
;
long
f_bsize
;
long
f_bsize
;
...
...
net/bridge/netfilter/ebtables.c
View file @
8e517818
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* ebtables
* ebtables
*
*
* Author:
* Author:
* Bart De Schuymer <b
art.de.schuymer
@pandora.be>
* Bart De Schuymer <b
dschuym
@pandora.be>
*
*
* ebtables.c,v 2.0, July, 2002
* ebtables.c,v 2.0, July, 2002
*
*
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
* 2 of the License, or (at your option) any later version.
* 2 of the License, or (at your option) any later version.
*/
*/
/
/ used for print_string
/
* used for print_string */
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/tty.h>
...
@@ -27,18 +27,20 @@
...
@@ -27,18 +27,20 @@
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <linux/smp.h>
#include <linux/smp.h>
#include <net/sock.h>
#include <net/sock.h>
/
/ needed for logical [in,out]-dev filtering
/
* needed for logical [in,out]-dev filtering */
#include "../br_private.h"
#include "../br_private.h"
/
/ list_named_find
/
* list_named_find */
#define ASSERT_READ_LOCK(x)
#define ASSERT_READ_LOCK(x)
#define ASSERT_WRITE_LOCK(x)
#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/listhelp.h>
#include <linux/netfilter_ipv4/listhelp.h>
#if 0 // use this for remote debugging
#if 0
// Copyright (C) 1998 by Ori Pomerantz
/* use this for remote debugging
// Print the string to the appropriate tty, the one
* Copyright (C) 1998 by Ori Pomerantz
// the current task uses
* Print the string to the appropriate tty, the one
* the current task uses
*/
static void print_string(char *str)
static void print_string(char *str)
{
{
struct tty_struct *my_tty;
struct tty_struct *my_tty;
...
@@ -55,20 +57,22 @@ static void print_string(char *str)
...
@@ -55,20 +57,22 @@ static void print_string(char *str)
#else
#else
#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
"report to author: "format, ## args)
"report to author: "format, ## args)
/
/ #define BUGPRINT(format, args...)
/
* #define BUGPRINT(format, args...) */
#endif
#endif
#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
": out of memory: "format, ## args)
": out of memory: "format, ## args)
/
/ #define MEMPRINT(format, args...)
/
* #define MEMPRINT(format, args...) */
// Each cpu has its own set of counters, so there is no need for write_lock in
/*
// the softirq
* Each cpu has its own set of counters, so there is no need for write_lock in
// For reading or updating the counters, the user context needs to
* the softirq
// get a write_lock
* For reading or updating the counters, the user context needs to
* get a write_lock
*/
/
/ The size of each set of counters is altered to get cache alignment
/
* The size of each set of counters is altered to get cache alignment */
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
...
@@ -91,7 +95,7 @@ static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
...
@@ -91,7 +95,7 @@ static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
{
{
w
->
u
.
watcher
->
watcher
(
skb
,
in
,
out
,
w
->
data
,
w
->
u
.
watcher
->
watcher
(
skb
,
in
,
out
,
w
->
data
,
w
->
watcher_size
);
w
->
watcher_size
);
/
/ watchers don't give a verdict
/
* watchers don't give a verdict */
return
0
;
return
0
;
}
}
...
@@ -113,7 +117,7 @@ static inline int ebt_dev_check(char *entry, const struct net_device *device)
...
@@ -113,7 +117,7 @@ static inline int ebt_dev_check(char *entry, const struct net_device *device)
}
}
#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
/
/ process standard matches
/
* process standard matches */
static
inline
int
ebt_basic_match
(
struct
ebt_entry
*
e
,
struct
ethhdr
*
h
,
static
inline
int
ebt_basic_match
(
struct
ebt_entry
*
e
,
struct
ethhdr
*
h
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
)
const
struct
net_device
*
in
,
const
struct
net_device
*
out
)
{
{
...
@@ -156,7 +160,7 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
...
@@ -156,7 +160,7 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
return
0
;
return
0
;
}
}
/
/ Do some firewalling
/
* Do some firewalling */
unsigned
int
ebt_do_table
(
unsigned
int
hook
,
struct
sk_buff
**
pskb
,
unsigned
int
ebt_do_table
(
unsigned
int
hook
,
struct
sk_buff
**
pskb
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
struct
ebt_table
*
table
)
struct
ebt_table
*
table
)
...
@@ -182,7 +186,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -182,7 +186,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
nentries
=
private
->
hook_entry
[
hook
]
->
nentries
;
nentries
=
private
->
hook_entry
[
hook
]
->
nentries
;
point
=
(
struct
ebt_entry
*
)(
private
->
hook_entry
[
hook
]
->
data
);
point
=
(
struct
ebt_entry
*
)(
private
->
hook_entry
[
hook
]
->
data
);
counter_base
=
cb_base
+
private
->
hook_entry
[
hook
]
->
counter_offset
;
counter_base
=
cb_base
+
private
->
hook_entry
[
hook
]
->
counter_offset
;
/
/ base for chain jumps
/
* base for chain jumps */
base
=
private
->
entries
;
base
=
private
->
entries
;
i
=
0
;
i
=
0
;
while
(
i
<
nentries
)
{
while
(
i
<
nentries
)
{
...
@@ -192,18 +196,18 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -192,18 +196,18 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
if
(
EBT_MATCH_ITERATE
(
point
,
ebt_do_match
,
*
pskb
,
in
,
out
)
!=
0
)
if
(
EBT_MATCH_ITERATE
(
point
,
ebt_do_match
,
*
pskb
,
in
,
out
)
!=
0
)
goto
letscontinue
;
goto
letscontinue
;
/
/ increase counter
/
* increase counter */
(
*
(
counter_base
+
i
)).
pcnt
++
;
(
*
(
counter_base
+
i
)).
pcnt
++
;
(
*
(
counter_base
+
i
)).
bcnt
+=
(
**
pskb
).
len
;
(
*
(
counter_base
+
i
)).
bcnt
+=
(
**
pskb
).
len
;
/
/
these should only watch: not modify, nor tell us
/
*
these should only watch: not modify, nor tell us
// what to do with the packet
what to do with the packet */
EBT_WATCHER_ITERATE
(
point
,
ebt_do_watcher
,
*
pskb
,
in
,
EBT_WATCHER_ITERATE
(
point
,
ebt_do_watcher
,
*
pskb
,
in
,
out
);
out
);
t
=
(
struct
ebt_entry_target
*
)
t
=
(
struct
ebt_entry_target
*
)
(((
char
*
)
point
)
+
point
->
target_offset
);
(((
char
*
)
point
)
+
point
->
target_offset
);
/
/ standard target
/
* standard target */
if
(
!
t
->
u
.
target
->
target
)
if
(
!
t
->
u
.
target
->
target
)
verdict
=
((
struct
ebt_standard_target
*
)
t
)
->
verdict
;
verdict
=
((
struct
ebt_standard_target
*
)
t
)
->
verdict
;
else
else
...
@@ -222,12 +226,12 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -222,12 +226,12 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
#ifdef CONFIG_NETFILTER_DEBUG
#ifdef CONFIG_NETFILTER_DEBUG
if
(
sp
==
0
)
{
if
(
sp
==
0
)
{
BUGPRINT
(
"RETURN on base chain"
);
BUGPRINT
(
"RETURN on base chain"
);
/
/ act like this is EBT_CONTINUE
/
* act like this is EBT_CONTINUE */
goto
letscontinue
;
goto
letscontinue
;
}
}
#endif
#endif
sp
--
;
sp
--
;
/
/ put all the local variables right
/
* put all the local variables right */
i
=
cs
[
sp
].
n
;
i
=
cs
[
sp
].
n
;
chaininfo
=
cs
[
sp
].
chaininfo
;
chaininfo
=
cs
[
sp
].
chaininfo
;
nentries
=
chaininfo
->
nentries
;
nentries
=
chaininfo
->
nentries
;
...
@@ -245,7 +249,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -245,7 +249,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
return
NF_DROP
;
return
NF_DROP
;
}
}
#endif
#endif
/
/ jump to a udc
/
* jump to a udc */
cs
[
sp
].
n
=
i
+
1
;
cs
[
sp
].
n
=
i
+
1
;
cs
[
sp
].
chaininfo
=
chaininfo
;
cs
[
sp
].
chaininfo
=
chaininfo
;
cs
[
sp
].
e
=
(
struct
ebt_entry
*
)
cs
[
sp
].
e
=
(
struct
ebt_entry
*
)
...
@@ -270,7 +274,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -270,7 +274,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
i
++
;
i
++
;
}
}
/
/ I actually like this :)
/
* I actually like this :) */
if
(
chaininfo
->
policy
==
EBT_RETURN
)
if
(
chaininfo
->
policy
==
EBT_RETURN
)
goto
letsreturn
;
goto
letsreturn
;
if
(
chaininfo
->
policy
==
EBT_ACCEPT
)
{
if
(
chaininfo
->
policy
==
EBT_ACCEPT
)
{
...
@@ -281,7 +285,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -281,7 +285,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
return
NF_DROP
;
return
NF_DROP
;
}
}
/
/ If it succeeds, returns element and locks mutex
/
* If it succeeds, returns element and locks mutex */
static
inline
void
*
static
inline
void
*
find_inlist_lock_noload
(
struct
list_head
*
head
,
const
char
*
name
,
int
*
error
,
find_inlist_lock_noload
(
struct
list_head
*
head
,
const
char
*
name
,
int
*
error
,
struct
semaphore
*
mutex
)
struct
semaphore
*
mutex
)
...
@@ -359,14 +363,15 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
...
@@ -359,14 +363,15 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
if
(
!
match
)
if
(
!
match
)
return
ret
;
return
ret
;
m
->
u
.
match
=
match
;
m
->
u
.
match
=
match
;
if
(
match
->
me
)
if
(
!
try_module_get
(
match
->
me
))
{
__MOD_INC_USE_COUNT
(
match
->
me
);
up
(
&
ebt_mutex
);
return
-
EINVAL
;
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
if
(
match
->
check
&&
if
(
match
->
check
&&
match
->
check
(
name
,
hookmask
,
e
,
m
->
data
,
m
->
match_size
)
!=
0
)
{
match
->
check
(
name
,
hookmask
,
e
,
m
->
data
,
m
->
match_size
)
!=
0
)
{
BUGPRINT
(
"match->check failed
\n
"
);
BUGPRINT
(
"match->check failed
\n
"
);
if
(
match
->
me
)
module_put
(
match
->
me
);
__MOD_DEC_USE_COUNT
(
match
->
me
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
(
*
cnt
)
++
;
(
*
cnt
)
++
;
...
@@ -387,22 +392,25 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
...
@@ -387,22 +392,25 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
if
(
!
watcher
)
if
(
!
watcher
)
return
ret
;
return
ret
;
w
->
u
.
watcher
=
watcher
;
w
->
u
.
watcher
=
watcher
;
if
(
watcher
->
me
)
if
(
!
try_module_get
(
watcher
->
me
))
{
__MOD_INC_USE_COUNT
(
watcher
->
me
);
up
(
&
ebt_mutex
);
return
-
EINVAL
;
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
if
(
watcher
->
check
&&
if
(
watcher
->
check
&&
watcher
->
check
(
name
,
hookmask
,
e
,
w
->
data
,
w
->
watcher_size
)
!=
0
)
{
watcher
->
check
(
name
,
hookmask
,
e
,
w
->
data
,
w
->
watcher_size
)
!=
0
)
{
BUGPRINT
(
"watcher->check failed
\n
"
);
BUGPRINT
(
"watcher->check failed
\n
"
);
if
(
watcher
->
me
)
module_put
(
watcher
->
me
);
__MOD_DEC_USE_COUNT
(
watcher
->
me
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
(
*
cnt
)
++
;
(
*
cnt
)
++
;
return
0
;
return
0
;
}
}
// this one is very careful, as it is the first function
/*
// to parse the userspace data
* this one is very careful, as it is the first function
* to parse the userspace data
*/
static
inline
int
static
inline
int
ebt_check_entry_size_and_hooks
(
struct
ebt_entry
*
e
,
ebt_check_entry_size_and_hooks
(
struct
ebt_entry
*
e
,
struct
ebt_table_info
*
newinfo
,
char
*
base
,
char
*
limit
,
struct
ebt_table_info
*
newinfo
,
char
*
base
,
char
*
limit
,
...
@@ -418,24 +426,24 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
...
@@ -418,24 +426,24 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
(
char
*
)
e
-
newinfo
->
entries
)
(
char
*
)
e
-
newinfo
->
entries
)
break
;
break
;
}
}
/
/
beginning of a new chain
/
*
beginning of a new chain
// if i == NF_BR_NUMHOOKS it must be a user defined chain
if i == NF_BR_NUMHOOKS it must be a user defined chain */
if
(
i
!=
NF_BR_NUMHOOKS
||
!
(
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
))
{
if
(
i
!=
NF_BR_NUMHOOKS
||
!
(
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
))
{
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
!=
0
)
{
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
!=
0
)
{
/
/
we make userspace set this right,
/
*
we make userspace set this right,
// so there is no misunderstanding
so there is no misunderstanding */
BUGPRINT
(
"EBT_ENTRY_OR_ENTRIES shouldn't be set "
BUGPRINT
(
"EBT_ENTRY_OR_ENTRIES shouldn't be set "
"in distinguisher
\n
"
);
"in distinguisher
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/
this checks if the previous chain has as many entries
/
*
this checks if the previous chain has as many entries
// as it said it has
as it said it has */
if
(
*
n
!=
*
cnt
)
{
if
(
*
n
!=
*
cnt
)
{
BUGPRINT
(
"nentries does not equal the nr of entries "
BUGPRINT
(
"nentries does not equal the nr of entries "
"in the chain
\n
"
);
"in the chain
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/ before we look at the struct, be sure it is not too big
/
* before we look at the struct, be sure it is not too big */
if
((
char
*
)
hook_entries
[
i
]
+
sizeof
(
struct
ebt_entries
)
if
((
char
*
)
hook_entries
[
i
]
+
sizeof
(
struct
ebt_entries
)
>
limit
)
{
>
limit
)
{
BUGPRINT
(
"entries_size too small
\n
"
);
BUGPRINT
(
"entries_size too small
\n
"
);
...
@@ -443,14 +451,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
...
@@ -443,14 +451,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
}
}
if
(((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_DROP
&&
if
(((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_DROP
&&
((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_ACCEPT
)
{
((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_ACCEPT
)
{
/
/ only RETURN from udc
/
* only RETURN from udc */
if
(
i
!=
NF_BR_NUMHOOKS
||
if
(
i
!=
NF_BR_NUMHOOKS
||
((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_RETURN
)
{
((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_RETURN
)
{
BUGPRINT
(
"bad policy
\n
"
);
BUGPRINT
(
"bad policy
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
}
}
if
(
i
==
NF_BR_NUMHOOKS
)
/
/ it's a user defined chain
if
(
i
==
NF_BR_NUMHOOKS
)
/
* it's a user defined chain */
(
*
udc_cnt
)
++
;
(
*
udc_cnt
)
++
;
else
else
newinfo
->
hook_entry
[
i
]
=
(
struct
ebt_entries
*
)
e
;
newinfo
->
hook_entry
[
i
]
=
(
struct
ebt_entries
*
)
e
;
...
@@ -462,14 +470,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
...
@@ -462,14 +470,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
*
cnt
=
0
;
*
cnt
=
0
;
return
0
;
return
0
;
}
}
/
/ a plain old entry, heh
/
* a plain old entry, heh */
if
(
sizeof
(
struct
ebt_entry
)
>
e
->
watchers_offset
||
if
(
sizeof
(
struct
ebt_entry
)
>
e
->
watchers_offset
||
e
->
watchers_offset
>
e
->
target_offset
||
e
->
watchers_offset
>
e
->
target_offset
||
e
->
target_offset
>=
e
->
next_offset
)
{
e
->
target_offset
>=
e
->
next_offset
)
{
BUGPRINT
(
"entry offsets not in right order
\n
"
);
BUGPRINT
(
"entry offsets not in right order
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/ this is not checked anywhere else
/
* this is not checked anywhere else */
if
(
e
->
next_offset
-
e
->
target_offset
<
sizeof
(
struct
ebt_entry_target
))
{
if
(
e
->
next_offset
-
e
->
target_offset
<
sizeof
(
struct
ebt_entry_target
))
{
BUGPRINT
(
"target size too small
\n
"
);
BUGPRINT
(
"target size too small
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -487,8 +495,10 @@ struct ebt_cl_stack
...
@@ -487,8 +495,10 @@ struct ebt_cl_stack
unsigned
int
hookmask
;
unsigned
int
hookmask
;
};
};
// we need these positions to check that the jumps to a different part of the
/*
// entries is a jump to the beginning of a new chain.
* we need these positions to check that the jumps to a different part of the
* entries is a jump to the beginning of a new chain.
*/
static
inline
int
static
inline
int
ebt_get_udc_positions
(
struct
ebt_entry
*
e
,
struct
ebt_table_info
*
newinfo
,
ebt_get_udc_positions
(
struct
ebt_entry
*
e
,
struct
ebt_table_info
*
newinfo
,
struct
ebt_entries
**
hook_entries
,
unsigned
int
*
n
,
unsigned
int
valid_hooks
,
struct
ebt_entries
**
hook_entries
,
unsigned
int
*
n
,
unsigned
int
valid_hooks
,
...
@@ -496,7 +506,7 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -496,7 +506,7 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
{
{
int
i
;
int
i
;
/
/ we're only interested in chain starts
/
* we're only interested in chain starts */
if
(
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
if
(
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
return
0
;
return
0
;
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
...
@@ -505,12 +515,12 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -505,12 +515,12 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
if
(
newinfo
->
hook_entry
[
i
]
==
(
struct
ebt_entries
*
)
e
)
if
(
newinfo
->
hook_entry
[
i
]
==
(
struct
ebt_entries
*
)
e
)
break
;
break
;
}
}
/
/ only care about udc
/
* only care about udc */
if
(
i
!=
NF_BR_NUMHOOKS
)
if
(
i
!=
NF_BR_NUMHOOKS
)
return
0
;
return
0
;
udc
[
*
n
].
cs
.
chaininfo
=
(
struct
ebt_entries
*
)
e
;
udc
[
*
n
].
cs
.
chaininfo
=
(
struct
ebt_entries
*
)
e
;
/
/ these initialisations are depended on later in check_chainloops()
/
* these initialisations are depended on later in check_chainloops() */
udc
[
*
n
].
cs
.
n
=
0
;
udc
[
*
n
].
cs
.
n
=
0
;
udc
[
*
n
].
hookmask
=
0
;
udc
[
*
n
].
hookmask
=
0
;
...
@@ -525,8 +535,7 @@ ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
...
@@ -525,8 +535,7 @@ ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
return
1
;
return
1
;
if
(
m
->
u
.
match
->
destroy
)
if
(
m
->
u
.
match
->
destroy
)
m
->
u
.
match
->
destroy
(
m
->
data
,
m
->
match_size
);
m
->
u
.
match
->
destroy
(
m
->
data
,
m
->
match_size
);
if
(
m
->
u
.
match
->
me
)
module_put
(
m
->
u
.
match
->
me
);
__MOD_DEC_USE_COUNT
(
m
->
u
.
match
->
me
);
return
0
;
return
0
;
}
}
...
@@ -538,8 +547,7 @@ ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
...
@@ -538,8 +547,7 @@ ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
return
1
;
return
1
;
if
(
w
->
u
.
watcher
->
destroy
)
if
(
w
->
u
.
watcher
->
destroy
)
w
->
u
.
watcher
->
destroy
(
w
->
data
,
w
->
watcher_size
);
w
->
u
.
watcher
->
destroy
(
w
->
data
,
w
->
watcher_size
);
if
(
w
->
u
.
watcher
->
me
)
module_put
(
w
->
u
.
watcher
->
me
);
__MOD_DEC_USE_COUNT
(
w
->
u
.
watcher
->
me
);
return
0
;
return
0
;
}
}
...
@@ -551,7 +559,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
...
@@ -551,7 +559,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
==
0
)
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
==
0
)
return
0
;
return
0
;
/
/ we're done
/
* we're done */
if
(
cnt
&&
(
*
cnt
)
--
==
0
)
if
(
cnt
&&
(
*
cnt
)
--
==
0
)
return
1
;
return
1
;
EBT_WATCHER_ITERATE
(
e
,
ebt_cleanup_watcher
,
NULL
);
EBT_WATCHER_ITERATE
(
e
,
ebt_cleanup_watcher
,
NULL
);
...
@@ -559,8 +567,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
...
@@ -559,8 +567,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
t
=
(
struct
ebt_entry_target
*
)(((
char
*
)
e
)
+
e
->
target_offset
);
t
=
(
struct
ebt_entry_target
*
)(((
char
*
)
e
)
+
e
->
target_offset
);
if
(
t
->
u
.
target
->
destroy
)
if
(
t
->
u
.
target
->
destroy
)
t
->
u
.
target
->
destroy
(
t
->
data
,
t
->
target_size
);
t
->
u
.
target
->
destroy
(
t
->
data
,
t
->
target_size
);
if
(
t
->
u
.
target
->
me
)
module_put
(
t
->
u
.
target
->
me
);
__MOD_DEC_USE_COUNT
(
t
->
u
.
target
->
me
);
return
0
;
return
0
;
}
}
...
@@ -575,7 +582,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -575,7 +582,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
unsigned
int
i
,
j
,
hook
=
0
,
hookmask
=
0
;
unsigned
int
i
,
j
,
hook
=
0
,
hookmask
=
0
;
int
ret
;
int
ret
;
/
/ Don't mess with the struct ebt_entries
/
* don't mess with the struct ebt_entries */
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
==
0
)
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
==
0
)
return
0
;
return
0
;
...
@@ -591,7 +598,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -591,7 +598,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
BUGPRINT
(
"NOPROTO & 802_3 not allowed
\n
"
);
BUGPRINT
(
"NOPROTO & 802_3 not allowed
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/ what hook do we belong to?
/
* what hook do we belong to? */
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
if
((
valid_hooks
&
(
1
<<
i
))
==
0
)
if
((
valid_hooks
&
(
1
<<
i
))
==
0
)
continue
;
continue
;
...
@@ -600,8 +607,8 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -600,8 +607,8 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
else
else
break
;
break
;
}
}
/
/
(1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
/
*
(1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
// a base chain
a base chain */
if
(
i
<
NF_BR_NUMHOOKS
)
if
(
i
<
NF_BR_NUMHOOKS
)
hookmask
=
(
1
<<
hook
)
|
(
1
<<
NF_BR_NUMHOOKS
);
hookmask
=
(
1
<<
hook
)
|
(
1
<<
NF_BR_NUMHOOKS
);
else
{
else
{
...
@@ -625,8 +632,10 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -625,8 +632,10 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
target
=
find_target_lock
(
t
->
u
.
name
,
&
ret
,
&
ebt_mutex
);
target
=
find_target_lock
(
t
->
u
.
name
,
&
ret
,
&
ebt_mutex
);
if
(
!
target
)
if
(
!
target
)
goto
cleanup_watchers
;
goto
cleanup_watchers
;
if
(
target
->
me
)
if
(
!
try_module_get
(
target
->
me
))
{
__MOD_INC_USE_COUNT
(
target
->
me
);
up
(
&
ebt_mutex
);
goto
cleanup_watchers
;
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
t
->
u
.
target
=
target
;
t
->
u
.
target
=
target
;
...
@@ -647,8 +656,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -647,8 +656,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
sizeof
(
struct
ebt_entry_target
)
>
e
->
next_offset
)
||
sizeof
(
struct
ebt_entry_target
)
>
e
->
next_offset
)
||
(
t
->
u
.
target
->
check
&&
(
t
->
u
.
target
->
check
&&
t
->
u
.
target
->
check
(
name
,
hookmask
,
e
,
t
->
data
,
t
->
target_size
)
!=
0
)){
t
->
u
.
target
->
check
(
name
,
hookmask
,
e
,
t
->
data
,
t
->
target_size
)
!=
0
)){
if
(
t
->
u
.
target
->
me
)
module_put
(
t
->
u
.
target
->
me
);
__MOD_DEC_USE_COUNT
(
t
->
u
.
target
->
me
);
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
goto
cleanup_watchers
;
goto
cleanup_watchers
;
}
}
...
@@ -661,10 +669,12 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -661,10 +669,12 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
return
ret
;
return
ret
;
}
}
// checks for loops and sets the hook mask for udc
/*
// the hook mask for udc tells us from which base chains the udc can be
* checks for loops and sets the hook mask for udc
// accessed. This mask is a parameter to the check() functions of the extensions
* the hook mask for udc tells us from which base chains the udc can be
int
check_chainloops
(
struct
ebt_entries
*
chain
,
struct
ebt_cl_stack
*
cl_s
,
* accessed. This mask is a parameter to the check() functions of the extensions
*/
static
int
check_chainloops
(
struct
ebt_entries
*
chain
,
struct
ebt_cl_stack
*
cl_s
,
unsigned
int
udc_cnt
,
unsigned
int
hooknr
,
char
*
base
)
unsigned
int
udc_cnt
,
unsigned
int
hooknr
,
char
*
base
)
{
{
int
i
,
chain_nr
=
-
1
,
pos
=
0
,
nentries
=
chain
->
nentries
,
verdict
;
int
i
,
chain_nr
=
-
1
,
pos
=
0
,
nentries
=
chain
->
nentries
,
verdict
;
...
@@ -672,9 +682,9 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -672,9 +682,9 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
struct
ebt_entry_target
*
t
;
struct
ebt_entry_target
*
t
;
while
(
pos
<
nentries
||
chain_nr
!=
-
1
)
{
while
(
pos
<
nentries
||
chain_nr
!=
-
1
)
{
/
/ end of udc, go back one 'recursion' step
/
* end of udc, go back one 'recursion' step */
if
(
pos
==
nentries
)
{
if
(
pos
==
nentries
)
{
/
/ put back values of the time when this chain was called
/
* put back values of the time when this chain was called */
e
=
cl_s
[
chain_nr
].
cs
.
e
;
e
=
cl_s
[
chain_nr
].
cs
.
e
;
if
(
cl_s
[
chain_nr
].
from
!=
-
1
)
if
(
cl_s
[
chain_nr
].
from
!=
-
1
)
nentries
=
nentries
=
...
@@ -682,7 +692,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -682,7 +692,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
else
else
nentries
=
chain
->
nentries
;
nentries
=
chain
->
nentries
;
pos
=
cl_s
[
chain_nr
].
cs
.
n
;
pos
=
cl_s
[
chain_nr
].
cs
.
n
;
/
/ make sure we won't see a loop that isn't one
/
* make sure we won't see a loop that isn't one */
cl_s
[
chain_nr
].
cs
.
n
=
0
;
cl_s
[
chain_nr
].
cs
.
n
=
0
;
chain_nr
=
cl_s
[
chain_nr
].
from
;
chain_nr
=
cl_s
[
chain_nr
].
from
;
if
(
pos
==
nentries
)
if
(
pos
==
nentries
)
...
@@ -698,13 +708,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -698,13 +708,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
return
-
1
;
return
-
1
;
}
}
verdict
=
((
struct
ebt_standard_target
*
)
t
)
->
verdict
;
verdict
=
((
struct
ebt_standard_target
*
)
t
)
->
verdict
;
if
(
verdict
>=
0
)
{
/
/ jump to another chain
if
(
verdict
>=
0
)
{
/
* jump to another chain */
struct
ebt_entries
*
hlp2
=
struct
ebt_entries
*
hlp2
=
(
struct
ebt_entries
*
)(
base
+
verdict
);
(
struct
ebt_entries
*
)(
base
+
verdict
);
for
(
i
=
0
;
i
<
udc_cnt
;
i
++
)
for
(
i
=
0
;
i
<
udc_cnt
;
i
++
)
if
(
hlp2
==
cl_s
[
i
].
cs
.
chaininfo
)
if
(
hlp2
==
cl_s
[
i
].
cs
.
chaininfo
)
break
;
break
;
/
/ bad destination or loop
/
* bad destination or loop */
if
(
i
==
udc_cnt
)
{
if
(
i
==
udc_cnt
)
{
BUGPRINT
(
"bad destination
\n
"
);
BUGPRINT
(
"bad destination
\n
"
);
return
-
1
;
return
-
1
;
...
@@ -713,7 +723,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -713,7 +723,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
BUGPRINT
(
"loop
\n
"
);
BUGPRINT
(
"loop
\n
"
);
return
-
1
;
return
-
1
;
}
}
/
/ this can't be 0, so the above test is correct
/
* this can't be 0, so the above test is correct */
cl_s
[
i
].
cs
.
n
=
pos
+
1
;
cl_s
[
i
].
cs
.
n
=
pos
+
1
;
pos
=
0
;
pos
=
0
;
cl_s
[
i
].
cs
.
e
=
((
void
*
)
e
+
e
->
next_offset
);
cl_s
[
i
].
cs
.
e
=
((
void
*
)
e
+
e
->
next_offset
);
...
@@ -721,7 +731,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -721,7 +731,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
nentries
=
hlp2
->
nentries
;
nentries
=
hlp2
->
nentries
;
cl_s
[
i
].
from
=
chain_nr
;
cl_s
[
i
].
from
=
chain_nr
;
chain_nr
=
i
;
chain_nr
=
i
;
/
/ this udc is accessible from the base chain for hooknr
/
* this udc is accessible from the base chain for hooknr */
cl_s
[
i
].
hookmask
|=
(
1
<<
hooknr
);
cl_s
[
i
].
hookmask
|=
(
1
<<
hooknr
);
continue
;
continue
;
}
}
...
@@ -732,13 +742,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -732,13 +742,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
return
0
;
return
0
;
}
}
/
/ do the parsing of the table/chains/entries/matches/watchers/targets, heh
/
* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
static
int
translate_table
(
struct
ebt_replace
*
repl
,
static
int
translate_table
(
struct
ebt_replace
*
repl
,
struct
ebt_table_info
*
newinfo
)
struct
ebt_table_info
*
newinfo
)
{
{
unsigned
int
i
,
j
,
k
,
udc_cnt
;
unsigned
int
i
,
j
,
k
,
udc_cnt
;
int
ret
;
int
ret
;
struct
ebt_cl_stack
*
cl_s
=
NULL
;
/
/ used in the checking for chain loops
struct
ebt_cl_stack
*
cl_s
=
NULL
;
/
* used in the checking for chain loops */
i
=
0
;
i
=
0
;
while
(
i
<
NF_BR_NUMHOOKS
&&
!
(
repl
->
valid_hooks
&
(
1
<<
i
)))
while
(
i
<
NF_BR_NUMHOOKS
&&
!
(
repl
->
valid_hooks
&
(
1
<<
i
)))
...
@@ -751,8 +761,8 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -751,8 +761,8 @@ static int translate_table(struct ebt_replace *repl,
BUGPRINT
(
"Chains don't start at beginning
\n
"
);
BUGPRINT
(
"Chains don't start at beginning
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/
make sure chains are ordered after each other in same order
/
*
make sure chains are ordered after each other in same order
// as their corresponding hooks
as their corresponding hooks */
for
(
j
=
i
+
1
;
j
<
NF_BR_NUMHOOKS
;
j
++
)
{
for
(
j
=
i
+
1
;
j
<
NF_BR_NUMHOOKS
;
j
++
)
{
if
(
!
(
repl
->
valid_hooks
&
(
1
<<
j
)))
if
(
!
(
repl
->
valid_hooks
&
(
1
<<
j
)))
continue
;
continue
;
...
@@ -769,12 +779,12 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -769,12 +779,12 @@ static int translate_table(struct ebt_replace *repl,
newinfo
->
entries_size
=
repl
->
entries_size
;
newinfo
->
entries_size
=
repl
->
entries_size
;
newinfo
->
nentries
=
repl
->
nentries
;
newinfo
->
nentries
=
repl
->
nentries
;
/
/ do some early checkings and initialize some things
/
* do some early checkings and initialize some things */
i
=
0
;
/
/ holds the expected nr. of entries for the chain
i
=
0
;
/
* holds the expected nr. of entries for the chain */
j
=
0
;
/
/ holds the up to now counted entries for the chain
j
=
0
;
/
* holds the up to now counted entries for the chain */
k
=
0
;
/
/
holds the total nr. of entries, should equal
k
=
0
;
/
*
holds the total nr. of entries, should equal
// newinfo->nentries afterwards
newinfo->nentries afterwards */
udc_cnt
=
0
;
/
/ will hold the nr. of user defined chains (udc)
udc_cnt
=
0
;
/
* will hold the nr. of user defined chains (udc) */
ret
=
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
ret
=
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
ebt_check_entry_size_and_hooks
,
newinfo
,
repl
->
entries
,
ebt_check_entry_size_and_hooks
,
newinfo
,
repl
->
entries
,
repl
->
entries
+
repl
->
entries_size
,
repl
->
hook_entry
,
&
i
,
&
j
,
&
k
,
repl
->
entries
+
repl
->
entries_size
,
repl
->
hook_entry
,
&
i
,
&
j
,
&
k
,
...
@@ -793,7 +803,7 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -793,7 +803,7 @@ static int translate_table(struct ebt_replace *repl,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/ check if all valid hooks have a chain
/
* check if all valid hooks have a chain */
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
if
(
newinfo
->
hook_entry
[
i
]
==
NULL
&&
if
(
newinfo
->
hook_entry
[
i
]
==
NULL
&&
(
repl
->
valid_hooks
&
(
1
<<
i
)))
{
(
repl
->
valid_hooks
&
(
1
<<
i
)))
{
...
@@ -802,11 +812,11 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -802,11 +812,11 @@ static int translate_table(struct ebt_replace *repl,
}
}
}
}
/
/ G
et the location of the udc, put them in an array
/
* g
et the location of the udc, put them in an array
// While we're at it, allocate the chainstack
while we're at it, allocate the chainstack */
if
(
udc_cnt
)
{
if
(
udc_cnt
)
{
/
/
this will get free'd in do_replace()/ebt_register_table()
/
*
this will get free'd in do_replace()/ebt_register_table()
// if an error occurs
if an error occurs */
newinfo
->
chainstack
=
(
struct
ebt_chainstack
**
)
newinfo
->
chainstack
=
(
struct
ebt_chainstack
**
)
vmalloc
(
NR_CPUS
*
sizeof
(
struct
ebt_chainstack
));
vmalloc
(
NR_CPUS
*
sizeof
(
struct
ebt_chainstack
));
if
(
!
newinfo
->
chainstack
)
if
(
!
newinfo
->
chainstack
)
...
@@ -827,11 +837,11 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -827,11 +837,11 @@ static int translate_table(struct ebt_replace *repl,
vmalloc
(
udc_cnt
*
sizeof
(
struct
ebt_cl_stack
));
vmalloc
(
udc_cnt
*
sizeof
(
struct
ebt_cl_stack
));
if
(
!
cl_s
)
if
(
!
cl_s
)
return
-
ENOMEM
;
return
-
ENOMEM
;
i
=
0
;
/
/ the i'th udc
i
=
0
;
/
* the i'th udc */
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
ebt_get_udc_positions
,
newinfo
,
repl
->
hook_entry
,
&
i
,
ebt_get_udc_positions
,
newinfo
,
repl
->
hook_entry
,
&
i
,
repl
->
valid_hooks
,
cl_s
);
repl
->
valid_hooks
,
cl_s
);
/
/ sanity check
/
* sanity check */
if
(
i
!=
udc_cnt
)
{
if
(
i
!=
udc_cnt
)
{
BUGPRINT
(
"i != udc_cnt
\n
"
);
BUGPRINT
(
"i != udc_cnt
\n
"
);
vfree
(
cl_s
);
vfree
(
cl_s
);
...
@@ -839,7 +849,7 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -839,7 +849,7 @@ static int translate_table(struct ebt_replace *repl,
}
}
}
}
/
/ Check for loops
/
* Check for loops */
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
if
(
repl
->
valid_hooks
&
(
1
<<
i
))
if
(
repl
->
valid_hooks
&
(
1
<<
i
))
if
(
check_chainloops
(
newinfo
->
hook_entry
[
i
],
if
(
check_chainloops
(
newinfo
->
hook_entry
[
i
],
...
@@ -849,17 +859,17 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -849,17 +859,17 @@ static int translate_table(struct ebt_replace *repl,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/
we now know the following (along with E=mc):
/
*
we now know the following (along with E=mc):
//
- the nr of entries in each chain is right
- the nr of entries in each chain is right
//
- the size of the allocated space is right
- the size of the allocated space is right
//
- all valid hooks have a corresponding chain
- all valid hooks have a corresponding chain
//
- there are no loops
- there are no loops
//
- wrong data can still be on the level of a single entry
- wrong data can still be on the level of a single entry
//
- could be there are jumps to places that are not the
- could be there are jumps to places that are not the
//
beginning of a chain. This can only occur in chains that
beginning of a chain. This can only occur in chains that
// are not accessible from any base chains, so we don't care.
are not accessible from any base chains, so we don't care. */
/
/ used to know what we need to clean up if something goes wrong
/
* used to know what we need to clean up if something goes wrong */
i
=
0
;
i
=
0
;
ret
=
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
ret
=
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
ebt_check_entry
,
newinfo
,
repl
->
name
,
&
i
,
repl
->
valid_hooks
,
ebt_check_entry
,
newinfo
,
repl
->
name
,
&
i
,
repl
->
valid_hooks
,
...
@@ -873,17 +883,17 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -873,17 +883,17 @@ static int translate_table(struct ebt_replace *repl,
return
ret
;
return
ret
;
}
}
/
/ called under write_lock
/
* called under write_lock */
static
void
get_counters
(
struct
ebt_counter
*
oldcounters
,
static
void
get_counters
(
struct
ebt_counter
*
oldcounters
,
struct
ebt_counter
*
counters
,
unsigned
int
nentries
)
struct
ebt_counter
*
counters
,
unsigned
int
nentries
)
{
{
int
i
,
cpu
;
int
i
,
cpu
;
struct
ebt_counter
*
counter_base
;
struct
ebt_counter
*
counter_base
;
/
/ counters of cpu 0
/
* counters of cpu 0 */
memcpy
(
counters
,
oldcounters
,
memcpy
(
counters
,
oldcounters
,
sizeof
(
struct
ebt_counter
)
*
nentries
);
sizeof
(
struct
ebt_counter
)
*
nentries
);
/
/ add other counters to those of cpu 0
/
* add other counters to those of cpu 0 */
for
(
cpu
=
1
;
cpu
<
NR_CPUS
;
cpu
++
)
{
for
(
cpu
=
1
;
cpu
<
NR_CPUS
;
cpu
++
)
{
counter_base
=
COUNTER_BASE
(
oldcounters
,
nentries
,
cpu
);
counter_base
=
COUNTER_BASE
(
oldcounters
,
nentries
,
cpu
);
for
(
i
=
0
;
i
<
nentries
;
i
++
)
{
for
(
i
=
0
;
i
<
nentries
;
i
++
)
{
...
@@ -893,7 +903,7 @@ static void get_counters(struct ebt_counter *oldcounters,
...
@@ -893,7 +903,7 @@ static void get_counters(struct ebt_counter *oldcounters,
}
}
}
}
/
/ replace the table
/
* replace the table */
static
int
do_replace
(
void
*
user
,
unsigned
int
len
)
static
int
do_replace
(
void
*
user
,
unsigned
int
len
)
{
{
int
ret
,
i
,
countersize
;
int
ret
,
i
,
countersize
;
...
@@ -901,7 +911,7 @@ static int do_replace(void *user, unsigned int len)
...
@@ -901,7 +911,7 @@ static int do_replace(void *user, unsigned int len)
struct
ebt_replace
tmp
;
struct
ebt_replace
tmp
;
struct
ebt_table
*
t
;
struct
ebt_table
*
t
;
struct
ebt_counter
*
counterstmp
=
NULL
;
struct
ebt_counter
*
counterstmp
=
NULL
;
/
/ used to be able to unlock earlier
/
* used to be able to unlock earlier */
struct
ebt_table_info
*
table
;
struct
ebt_table_info
*
table
;
if
(
copy_from_user
(
&
tmp
,
user
,
sizeof
(
tmp
))
!=
0
)
if
(
copy_from_user
(
&
tmp
,
user
,
sizeof
(
tmp
))
!=
0
)
...
@@ -937,8 +947,8 @@ static int do_replace(void *user, unsigned int len)
...
@@ -937,8 +947,8 @@ static int do_replace(void *user, unsigned int len)
goto
free_entries
;
goto
free_entries
;
}
}
/
/
the user wants counters back
/
*
the user wants counters back
// the check on the size is done later, when we have the lock
the check on the size is done later, when we have the lock */
if
(
tmp
.
num_counters
)
{
if
(
tmp
.
num_counters
)
{
counterstmp
=
(
struct
ebt_counter
*
)
counterstmp
=
(
struct
ebt_counter
*
)
vmalloc
(
tmp
.
num_counters
*
sizeof
(
struct
ebt_counter
));
vmalloc
(
tmp
.
num_counters
*
sizeof
(
struct
ebt_counter
));
...
@@ -950,7 +960,7 @@ static int do_replace(void *user, unsigned int len)
...
@@ -950,7 +960,7 @@ static int do_replace(void *user, unsigned int len)
else
else
counterstmp
=
NULL
;
counterstmp
=
NULL
;
/
/ this can get initialized by translate_table()
/
* this can get initialized by translate_table() */
newinfo
->
chainstack
=
NULL
;
newinfo
->
chainstack
=
NULL
;
ret
=
translate_table
(
&
tmp
,
newinfo
);
ret
=
translate_table
(
&
tmp
,
newinfo
);
...
@@ -961,7 +971,7 @@ static int do_replace(void *user, unsigned int len)
...
@@ -961,7 +971,7 @@ static int do_replace(void *user, unsigned int len)
if
(
!
t
)
if
(
!
t
)
goto
free_iterate
;
goto
free_iterate
;
/
/ the table doesn't like it
/
* the table doesn't like it */
if
(
t
->
check
&&
(
ret
=
t
->
check
(
newinfo
,
tmp
.
valid_hooks
)))
if
(
t
->
check
&&
(
ret
=
t
->
check
(
newinfo
,
tmp
.
valid_hooks
)))
goto
free_unlock
;
goto
free_unlock
;
...
@@ -971,9 +981,9 @@ static int do_replace(void *user, unsigned int len)
...
@@ -971,9 +981,9 @@ static int do_replace(void *user, unsigned int len)
goto
free_unlock
;
goto
free_unlock
;
}
}
/
/ we have the mutex lock, so no danger in reading this pointer
/
* we have the mutex lock, so no danger in reading this pointer */
table
=
t
->
private
;
table
=
t
->
private
;
/
/ we need an atomic snapshot of the counters
/
* we need an atomic snapshot of the counters */
write_lock_bh
(
&
t
->
lock
);
write_lock_bh
(
&
t
->
lock
);
if
(
tmp
.
num_counters
)
if
(
tmp
.
num_counters
)
get_counters
(
t
->
private
->
counters
,
counterstmp
,
get_counters
(
t
->
private
->
counters
,
counterstmp
,
...
@@ -982,10 +992,10 @@ static int do_replace(void *user, unsigned int len)
...
@@ -982,10 +992,10 @@ static int do_replace(void *user, unsigned int len)
t
->
private
=
newinfo
;
t
->
private
=
newinfo
;
write_unlock_bh
(
&
t
->
lock
);
write_unlock_bh
(
&
t
->
lock
);
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
/
/ S
o, a user can change the chains while having messed up her counter
/
* s
o, a user can change the chains while having messed up her counter
//
allocation. Only reason why this is done is because this way the lock
allocation. Only reason why this is done is because this way the lock
//
is held only once, while this doesn't bring the kernel into a
is held only once, while this doesn't bring the kernel into a
// dangerous state.
dangerous state. */
if
(
tmp
.
num_counters
&&
if
(
tmp
.
num_counters
&&
copy_to_user
(
tmp
.
counters
,
counterstmp
,
copy_to_user
(
tmp
.
counters
,
counterstmp
,
tmp
.
num_counters
*
sizeof
(
struct
ebt_counter
)))
{
tmp
.
num_counters
*
sizeof
(
struct
ebt_counter
)))
{
...
@@ -995,7 +1005,7 @@ static int do_replace(void *user, unsigned int len)
...
@@ -995,7 +1005,7 @@ static int do_replace(void *user, unsigned int len)
else
else
ret
=
0
;
ret
=
0
;
/
/ decrease module count and free resources
/
* decrease module count and free resources */
EBT_ENTRY_ITERATE
(
table
->
entries
,
table
->
entries_size
,
EBT_ENTRY_ITERATE
(
table
->
entries
,
table
->
entries_size
,
ebt_cleanup_entry
,
NULL
);
ebt_cleanup_entry
,
NULL
);
...
@@ -1019,7 +1029,7 @@ static int do_replace(void *user, unsigned int len)
...
@@ -1019,7 +1029,7 @@ static int do_replace(void *user, unsigned int len)
free_counterstmp:
free_counterstmp:
if
(
counterstmp
)
if
(
counterstmp
)
vfree
(
counterstmp
);
vfree
(
counterstmp
);
/
/ can be initialized in translate_table()
/
* can be initialized in translate_table() */
if
(
newinfo
->
chainstack
)
{
if
(
newinfo
->
chainstack
)
{
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
vfree
(
newinfo
->
chainstack
[
i
]);
vfree
(
newinfo
->
chainstack
[
i
]);
...
@@ -1046,7 +1056,6 @@ int ebt_register_target(struct ebt_target *target)
...
@@ -1046,7 +1056,6 @@ int ebt_register_target(struct ebt_target *target)
return
-
EEXIST
;
return
-
EEXIST
;
}
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_INC_USE_COUNT
;
return
0
;
return
0
;
}
}
...
@@ -1056,7 +1065,6 @@ void ebt_unregister_target(struct ebt_target *target)
...
@@ -1056,7 +1065,6 @@ void ebt_unregister_target(struct ebt_target *target)
down
(
&
ebt_mutex
);
down
(
&
ebt_mutex
);
LIST_DELETE
(
&
ebt_targets
,
target
);
LIST_DELETE
(
&
ebt_targets
,
target
);
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_DEC_USE_COUNT
;
}
}
int
ebt_register_match
(
struct
ebt_match
*
match
)
int
ebt_register_match
(
struct
ebt_match
*
match
)
...
@@ -1071,7 +1079,6 @@ int ebt_register_match(struct ebt_match *match)
...
@@ -1071,7 +1079,6 @@ int ebt_register_match(struct ebt_match *match)
return
-
EEXIST
;
return
-
EEXIST
;
}
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_INC_USE_COUNT
;
return
0
;
return
0
;
}
}
...
@@ -1081,7 +1088,6 @@ void ebt_unregister_match(struct ebt_match *match)
...
@@ -1081,7 +1088,6 @@ void ebt_unregister_match(struct ebt_match *match)
down
(
&
ebt_mutex
);
down
(
&
ebt_mutex
);
LIST_DELETE
(
&
ebt_matches
,
match
);
LIST_DELETE
(
&
ebt_matches
,
match
);
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_DEC_USE_COUNT
;
}
}
int
ebt_register_watcher
(
struct
ebt_watcher
*
watcher
)
int
ebt_register_watcher
(
struct
ebt_watcher
*
watcher
)
...
@@ -1096,7 +1102,6 @@ int ebt_register_watcher(struct ebt_watcher *watcher)
...
@@ -1096,7 +1102,6 @@ int ebt_register_watcher(struct ebt_watcher *watcher)
return
-
EEXIST
;
return
-
EEXIST
;
}
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_INC_USE_COUNT
;
return
0
;
return
0
;
}
}
...
@@ -1106,7 +1111,6 @@ void ebt_unregister_watcher(struct ebt_watcher *watcher)
...
@@ -1106,7 +1111,6 @@ void ebt_unregister_watcher(struct ebt_watcher *watcher)
down
(
&
ebt_mutex
);
down
(
&
ebt_mutex
);
LIST_DELETE
(
&
ebt_watchers
,
watcher
);
LIST_DELETE
(
&
ebt_watchers
,
watcher
);
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_DEC_USE_COUNT
;
}
}
int
ebt_register_table
(
struct
ebt_table
*
table
)
int
ebt_register_table
(
struct
ebt_table
*
table
)
...
@@ -1138,7 +1142,7 @@ int ebt_register_table(struct ebt_table *table)
...
@@ -1138,7 +1142,7 @@ int ebt_register_table(struct ebt_table *table)
if
(
countersize
)
if
(
countersize
)
memset
(
newinfo
->
counters
,
0
,
countersize
);
memset
(
newinfo
->
counters
,
0
,
countersize
);
/
/ fill in newinfo and parse the entries
/
* fill in newinfo and parse the entries */
newinfo
->
chainstack
=
NULL
;
newinfo
->
chainstack
=
NULL
;
ret
=
translate_table
(
table
->
table
,
newinfo
);
ret
=
translate_table
(
table
->
table
,
newinfo
);
if
(
ret
!=
0
)
{
if
(
ret
!=
0
)
{
...
@@ -1165,7 +1169,6 @@ int ebt_register_table(struct ebt_table *table)
...
@@ -1165,7 +1169,6 @@ int ebt_register_table(struct ebt_table *table)
list_prepend
(
&
ebt_tables
,
table
);
list_prepend
(
&
ebt_tables
,
table
);
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_INC_USE_COUNT
;
return
0
;
return
0
;
free_unlock:
free_unlock:
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
...
@@ -1202,10 +1205,9 @@ void ebt_unregister_table(struct ebt_table *table)
...
@@ -1202,10 +1205,9 @@ void ebt_unregister_table(struct ebt_table *table)
vfree
(
table
->
private
->
chainstack
);
vfree
(
table
->
private
->
chainstack
);
}
}
vfree
(
table
->
private
);
vfree
(
table
->
private
);
MOD_DEC_USE_COUNT
;
}
}
/
/ userspace just supplied us with counters
/
* userspace just supplied us with counters */
static
int
update_counters
(
void
*
user
,
unsigned
int
len
)
static
int
update_counters
(
void
*
user
,
unsigned
int
len
)
{
{
int
i
,
ret
;
int
i
,
ret
;
...
@@ -1244,10 +1246,10 @@ static int update_counters(void *user, unsigned int len)
...
@@ -1244,10 +1246,10 @@ static int update_counters(void *user, unsigned int len)
goto
unlock_mutex
;
goto
unlock_mutex
;
}
}
/
/ we want an atomic add of the counters
/
* we want an atomic add of the counters */
write_lock_bh
(
&
t
->
lock
);
write_lock_bh
(
&
t
->
lock
);
/
/ we add to the counters of the first cpu
/
* we add to the counters of the first cpu */
for
(
i
=
0
;
i
<
hlp
.
num_counters
;
i
++
)
{
for
(
i
=
0
;
i
<
hlp
.
num_counters
;
i
++
)
{
t
->
private
->
counters
[
i
].
pcnt
+=
tmp
[
i
].
pcnt
;
t
->
private
->
counters
[
i
].
pcnt
+=
tmp
[
i
].
pcnt
;
t
->
private
->
counters
[
i
].
bcnt
+=
tmp
[
i
].
bcnt
;
t
->
private
->
counters
[
i
].
bcnt
+=
tmp
[
i
].
bcnt
;
...
@@ -1303,7 +1305,7 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
...
@@ -1303,7 +1305,7 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
return
0
;
return
0
;
}
}
/
/ called with ebt_mutex down
/
* called with ebt_mutex down */
static
int
copy_everything_to_user
(
struct
ebt_table
*
t
,
void
*
user
,
static
int
copy_everything_to_user
(
struct
ebt_table
*
t
,
void
*
user
,
int
*
len
,
int
cmd
)
int
*
len
,
int
cmd
)
{
{
...
@@ -1345,7 +1347,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user,
...
@@ -1345,7 +1347,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/ userspace might not need the counters
/
* userspace might not need the counters */
if
(
tmp
.
num_counters
)
{
if
(
tmp
.
num_counters
)
{
if
(
tmp
.
num_counters
!=
nentries
)
{
if
(
tmp
.
num_counters
!=
nentries
)
{
BUGPRINT
(
"Num_counters wrong
\n
"
);
BUGPRINT
(
"Num_counters wrong
\n
"
);
...
@@ -1374,7 +1376,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user,
...
@@ -1374,7 +1376,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user,
BUGPRINT
(
"Couldn't copy entries to userspace
\n
"
);
BUGPRINT
(
"Couldn't copy entries to userspace
\n
"
);
return
-
EFAULT
;
return
-
EFAULT
;
}
}
/
/ set the match/watcher/target names right
/
* set the match/watcher/target names right */
return
EBT_ENTRY_ITERATE
(
entries
,
entries_size
,
return
EBT_ENTRY_ITERATE
(
entries
,
entries_size
,
ebt_make_names
,
entries
,
tmp
.
entries
);
ebt_make_names
,
entries
,
tmp
.
entries
);
}
}
...
@@ -1465,14 +1467,14 @@ static int __init init(void)
...
@@ -1465,14 +1467,14 @@ static int __init init(void)
if
((
ret
=
nf_register_sockopt
(
&
ebt_sockopts
))
<
0
)
if
((
ret
=
nf_register_sockopt
(
&
ebt_sockopts
))
<
0
)
return
ret
;
return
ret
;
printk
(
"Ebtables v2.0 registered
"
);
printk
(
KERN_NOTICE
"Ebtables v2.0 registered
\n
"
);
return
0
;
return
0
;
}
}
static
void
__exit
fini
(
void
)
static
void
__exit
fini
(
void
)
{
{
nf_unregister_sockopt
(
&
ebt_sockopts
);
nf_unregister_sockopt
(
&
ebt_sockopts
);
printk
(
"Ebtables v2.0 unregistered
"
);
printk
(
KERN_NOTICE
"Ebtables v2.0 unregistered
\n
"
);
}
}
EXPORT_SYMBOL
(
ebt_register_table
);
EXPORT_SYMBOL
(
ebt_register_table
);
...
...
net/ipv4/route.c
View file @
8e517818
...
@@ -2672,11 +2672,13 @@ int __init ip_rt_init(void)
...
@@ -2672,11 +2672,13 @@ int __init ip_rt_init(void)
ip_rt_gc_interval
;
ip_rt_gc_interval
;
add_timer
(
&
rt_periodic_timer
);
add_timer
(
&
rt_periodic_timer
);
#ifdef CONFIG_PROC_FS
if
(
rt_cache_proc_init
())
if
(
rt_cache_proc_init
())
goto
out_enomem
;
goto
out_enomem
;
proc_net_create
(
"rt_cache_stat"
,
0
,
rt_cache_stat_get_info
);
proc_net_create
(
"rt_cache_stat"
,
0
,
rt_cache_stat_get_info
);
#ifdef CONFIG_NET_CLS_ROUTE
#ifdef CONFIG_NET_CLS_ROUTE
create_proc_read_entry
(
"net/rt_acct"
,
0
,
0
,
ip_rt_acct_read
,
NULL
);
create_proc_read_entry
(
"net/rt_acct"
,
0
,
0
,
ip_rt_acct_read
,
NULL
);
#endif
#endif
#endif
xfrm_init
();
xfrm_init
();
out:
out:
...
...
net/ipv4/tcp_ipv4.c
View file @
8e517818
...
@@ -2412,6 +2412,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
...
@@ -2412,6 +2412,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
read_unlock_bh
(
&
tp
->
syn_wait_lock
);
read_unlock_bh
(
&
tp
->
syn_wait_lock
);
}
}
case
TCP_SEQ_STATE_LISTENING
:
case
TCP_SEQ_STATE_LISTENING
:
if
(
v
!=
(
void
*
)
1
)
tcp_listen_unlock
();
tcp_listen_unlock
();
break
;
break
;
case
TCP_SEQ_STATE_TIME_WAIT
:
case
TCP_SEQ_STATE_TIME_WAIT
:
...
...
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