Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
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
Hide 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
))
return
;
goto
ack_tx_int
;
disable_tx_int:
return
;
up
->
curregs
[
R5
]
&=
~
TxENAB
;
write_zsreg
(
ZILOG_CHANNEL_FROM_PORT
(
&
up
->
port
),
R5
,
up
->
curregs
[
R5
]);
ack_tx_int:
sbus_writeb
(
RES_Tx_P
,
&
channel
->
control
);
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
(
&
up
->
port
);
channel
=
ZILOG_CHANNEL_FROM_PORT
(
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,7 +2412,8 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
...
@@ -2412,7 +2412,8 @@ 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
:
tcp_listen_unlock
();
if
(
v
!=
(
void
*
)
1
)
tcp_listen_unlock
();
break
;
break
;
case
TCP_SEQ_STATE_TIME_WAIT
:
case
TCP_SEQ_STATE_TIME_WAIT
:
case
TCP_SEQ_STATE_ESTABLISHED
:
case
TCP_SEQ_STATE_ESTABLISHED
:
...
...
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