Commit 8e517818 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://ppc.bkbits.net/for-linus-ppc64

into home.transmeta.com:/home/torvalds/v2.5/linux
parents a1940218 980e2c9b
...@@ -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 r4,0 100: li r9,0
b 90f b 90f
/* write fault, initial single-byte copy */ /* write fault, initial single-byte copy */
101: li r4,1 101: li r9,1
90: subf r5,r8,r5 90: subf r5,r8,r5
li r3,0 li r3,0
b 99f b 99f
/* read fault, initial word copy */ /* read fault, initial word copy */
102: li r4,0 102: li r9,0
b 91f b 91f
/* write fault, initial word copy */ /* write fault, initial word copy */
103: li r4,1 103: li r9,1
91: li r3,2 91: li r3,2
b 99f b 99f
...@@ -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 r4,0 104: li r9,0
b 92f b 92f
/* 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 r4,1 105: li r9,1
92: li r3,LG_CACHELINE_BYTES 92: li r3,LG_CACHELINE_BYTES
b 99f b 99f
/* read fault in final word loop */ /* read fault in final word loop */
108: li r4,0 108: li r9,0
b 93f b 93f
/* write fault in final word loop */ /* write fault in final word loop */
109: li r4,1 109: li r9,1
93: andi. r5,r5,3 93: andi. r5,r5,3
li r3,2 li r3,2
b 99f b 99f
/* read fault in final byte loop */ /* read fault in final byte loop */
110: li r4,0 110: li r9,0
b 94f b 94f
/* write fault in final byte loop */ /* write fault in final byte loop */
111: li r4,1 111: li r9,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 r4 is 0 for read or 1 for write. * r5 + (ctr << r3), and r9 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 120f /* shouldn't happen */
cmpwi 0,r9,0
bne 120f bne 120f
/* 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 130b
/* 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 31b,109b .long 31b,109b
.long 40b,110b .long 40b,110b
.long 41b,111b .long 41b,111b
.long 130b,132b
.long 131b,120b
.long 112b,120b .long 112b,120b
.long 114b,120b .long 114b,120b
.text .text
......
...@@ -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 */
......
...@@ -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
......
...@@ -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;
}
...@@ -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:
......
...@@ -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);
......
...@@ -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
......
...@@ -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, R3);
/* 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[R11] = TCBR | RCBR;
/* Program BAUD and clock source. */ /* Program BAUD and clock source. */
up->curregs[4] &= ~XCLK_MASK; up->curregs[R4] &= ~XCLK_MASK;
up->curregs[4] |= X16CLK; up->curregs[R4] |= X16CLK;
up->curregs[12] = brg & 0xff; up->curregs[R12] = brg & 0xff;
up->curregs[13] = (brg >> 8) & 0xff; up->curregs[R13] = (brg >> 8) & 0xff;
up->curregs[14] = BRSRC | BRENAB; up->curregs[R14] = 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);
......
...@@ -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>
......
...@@ -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 */
...@@ -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)
......
...@@ -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 */
...@@ -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;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ebtables * ebtables
* *
* Author: * Author:
* Bart De Schuymer <bart.de.schuymer@pandora.be> * Bart De Schuymer <bdschuym@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,
} }
} }
// Get the location of the udc, put them in an array /* get 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);
// So, a user can change the chains while having messed up her counter /* so, 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);
......
...@@ -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:
......
...@@ -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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment